proxy-target-class屬性值: FALSE 或 省略 基於接口(JDK || AspectJ )代理, TRUE 基於類 (CGLIB ) 代理。java
(通常而言,spring的xml中的標籤必定是在<beans> 中定義了xmlns及 xsi:schemaLocation 的標籤,並有【 xxxNamespaceHandler】 做爲xml元素的解析)spring
AopNamespaceHandler:對於<aop:config>的解析使用ConfigBeanDefinitionParser性能
private void configureAutoProxyCreator(ParserContext parserContext, Element element) { AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary(parserContext, element); }
執行進入AopNamespaceUtils.useClassProxyingIfNecessary方法: 優化
private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, @Nullable Element sourceElement) { if (sourceElement != null) { boolean proxyTargetClass = Boolean.parseBoolean(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE)); if (proxyTargetClass) { AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry); } boolean exposeProxy = Boolean.parseBoolean(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE)); if (exposeProxy) { AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry); } } }
proxy-target-class = true 則調用AopConfigUtils.forceAutoProxyCreatorToUseClassProxying方法,給beanDefinition對象綁定proxyTargetClass=trueui
public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) { if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) { BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME); definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE); } }
ProxyFactoryBean.getObject() 構建bean的代理對象:spa
調用 DefaultAopProxyFactory.createAopProxy方法來斷定使用哪一種代理方式.net
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { Class<?> targetClass = config.getTargetClass(); if (targetClass == null) { throw new AopConfigException("TargetSource cannot determine target class: " + "Either an interface or a target is required for proxy creation."); } if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); } return new ObjenesisCglibAopProxy(config); } else { return new JdkDynamicAopProxy(config); } }
終於看到JDK和CGLIB的字樣了,這個方法決定了是使用JDK動態代理仍是CGLIB動態代理。下面對if中的判斷邏輯逐個解釋代理
這個類的說明:code
specify {@code proxyTargetClass} to enforce a CGLIB proxy, or specify one or more interfaces to use a JDK dynamic proxy.
指定{@code proxyTargetClass}來強制執行CGLIB代理,或指定一個或多個接口以使用JDK動態代理xml
結合類說明和判斷邏輯,能夠得出結論:
指定proxyTargetClass=true後, target對象 非接口類型 && 非DK代理類 時,執行CGLIB代理!其餘狀況下都是用JDK代理