Spring MVC项目中以<aop:aspectj-autoproxy proxy-target-class="false" >方式开启aop动态代理,proxy-target-class默认false代表接口类动态代理默认使用JdkDynamicAopProxy,而非接口类使用ObjenesisCglibAopProxy,而proxy-target-class设置为true时全部使用ObjenesisCglibAopProxy。
JdkDynamicAopProxy实现InvocationHandler接口、invoke方法,在invoke方法中通过反射的方式调用原类方法,调用前后可实现AOP前后增强方法。
ObjenesisCglibAopProxy使用底层的字节码技术,对原类生成子类,对子类进行增强(因此类、方法均不能使用final关键字,同时不能增强private方法)。实现MethodInterceptor接口、intercept方法,intercept方法调用MethodProxy.invokeSuper()触发原方法,调用前后可实现AOP前后增强方法。
但项目开发过程中,debug定位问题时忽然注意到@Autowired注解的接口,注入的接口实现类动态代理使用的全是Cglib,第一反应可能是事务配置引起的问题,但检查声明式事务配置<tx:annotation-driven transaction-manager=“txManager”>发现proxy-target-class也未配置,默认值是false。
脑补AOP源码实现流程,以AopNameSpace为入口,init方法中AspectJAutoProxyBeanDefinitionParser的parse方法ProxyCreator的注册,然后进AopNameSpaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary()方法查看到BeanDefinition的获取,以及userClassProxyingIfNecessary对proxy-target-class、expose-proxy属性的处理,之后调用AbstractAutowireCapableBeanFactory.createBean()、doCreateBean()、populateBean()填充属性最后合并注册AnnotationAwareAspectJAutoProxyCreator为org.xxx.internalAutoProxyCreator实例,最后根据对象参数配置AbstractAutoCreator的postProcessBeforeInstantiation方法createProxy。
但我们的问题出在AnnotationAwareAspectJAutoProxyCreator实例创建的属性问题,因此跟前部分代码在
AopNameSpaceUtils.userClassProxyingIfNecessary()发现被调用3次,分别是<aop:aspectj-autoproxy/>、<tx:annotation-driven/>、<cache:annotation>3个标签,cache:annotation配置的proxy-target-class为true,至此问题原因找到。
我们项目虽然没有使用Spring Cache相关功能,但集成redis时配置了标签,说来全是泪。