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代理

相关文章
相关标签/搜索