proxy-target-class属性值决定是基于接口的还是基于类的代理被创建,
TRUE则是基于类的代理将起作用(需要cglib库), 为FALSE或者省略这个属性,则标准的JDK 基于接口的代理将起作用。
源码解析:
AopNamespaceHandler类,就是spring解析<aop:configproxy-target-class="true">配置的入口,(一般而言,spring的xml中的标签一定是在<beans> 中定义了xmlns及xsi:schemaLocation定义了,并有【 xxxNamespaceHandler】 作为xml元素的解析)
则可以看到init方法里注册了ConfigBeanDefinitionParser类来解析,这个类则是实际解析<aop:config proxy-target-class="true">的类
registerBeanDefinitionParser("config",new ConfigBeanDefinitionParser());
打开这个类搜索proxy-target-class,则可以看到configureAutoProxyCreator方法,这个方法则是解析proxy-target-class属性的方法
private void configureAutoProxyCreator(ParserContext parserContext, Element element) { AopNamespaceUtils.registerAspectJAutoProxyCreatorIfNecessary(parserContext, element);}
进入这个方法,再进入useClassProxyingIfNecessary方法则可以看到
boolean proxyTargetClass = Boolean.valueOf(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));if (proxyTargetClass) { AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);}
为true则调用forceAutoProxyCreatorToUseClassProxying方法,强制基于类来创建代理,从上面代码可以看出,不设置则默认为false
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); }}
此处可以看到,在bean定义对象中设置了proxyTargetClass属性,后面spring获取bean创建代理类的时候,会判断此属性类决定使用JdkDynamicAopProxy还是ObjenesisCglibAopProxy代理
打开DefaultAopProxyFactory类,查看createAopProxy方法
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()) { return new JdkDynamicAopProxy(config); } return new ObjenesisCglibAopProxy(config); } else { return new JdkDynamicAopProxy(config); }}
hasNoUserSuppliedProxyInterfaces方法则说明即使你未声明proxy-target-class="true" ,但运行类没有继承接口,spring也会自动使用CGLIB代理。
总结:高版本spring自动根据运行类选择JDK或CGLIB代理,我们无需设置proxy-target-class属性,JDK动态代理是模拟接口实现的方式,cglib是模拟子类继承的方式,一般采用前者,因为前者效率高, 后者不建议使用。