Spring的代理選擇

proxy-target-class屬性值: FALSE 或 省略 基於接口(JDK || AspectJ 代理TRUE 基於類 (CGLIB ) 代理。java

BeanDefinition設置proxyTargetClass屬性

(通常而言,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中的判斷邏輯逐個解釋代理

  • config.isOptimize():是否優化,看到否的邏輯是JDK,就能夠知道Spring認爲CGLIB動態代理的性能更高點。
  • config.isProxyTargetClass(): 是否直接代理目標類以及任何接口
  • hasNoUserSuppliedProxyInterfaces(config):是否沒有指定代理接口
  • targetClass.isInterface():肯定指定的對象是否表示接口類型
  • Proxy.isProxyClass(targetClass):是不是代理類

這個類的說明: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代理

相關文章
相關標籤/搜索