Spring代理同一个方法调用同一个对象中的兄弟方法的问题

版权声明:本文为博主原创文章,未经允许不得转载。 https://blog.csdn.net/qq_31142553/article/details/81781037

service有A、B两个方法,A方法无AOP,B方法有AOP。在A方法中调用了B方法。

  • 问题1:B方法AOP会不会生效?为什么?
  • 问题2:如果不会,怎么解决?

涉及的知识点:事务传播特性,嵌套事务

同一个方法调用同一个对象中的兄弟方法,基于JDK接口形式的动态代理,是不会生效的。
但是,基于cglib形式的动态代理,那就不一定了。

Spring的配置可以让你去选择使用哪种动态代理。

JDK动态代理基于接口,要生成代理类,是通过实现了一个接口生成的,但是代理类实现了相通的接口,他的实现从何而来,必须从一个目标对象target身上来,target作为方法调用的基础,然后在target前后左右做拦截。对于spring aop来说,我们平时加上@transactional注解的service类,实际上,就是target的类,我们在service方法内部调用另外一个兄弟service方法,实际上,就是target内部的调用,并没有走外层的拦截。

但是,cglib形式的动态代理,是基于继承的,代理类是继承一个目标类而来,这样,代理类还需要一个target吗?其实是不需要的, 因为在代理类的实例中,已经包含了一个父类对象super,我们只需要覆盖父类的方法,在super的前后左右做拦截,就可以完成动态代理。

但是,cglib继承模式中,也可以持有一个target属性,而忽略super,只是说,我们多了一个选择,可以不选择target,使用super,也可以使用一个target,而不使用super。

对于spring aop中的cglib形式动态代理来说,我们只是在service类上加了transactional注解,根本就不存在任何的target,因此,在spring aop中,cglib形式下的动态代理就是基于super的拦截。

好了,既然是基于super的拦截,cglib也是采用继承覆盖父类方法实现的,那么,在service类中,调用一个兄弟方法的时候,出现了一个很奇特的现象:那就是,你在service类中调用一个兄弟方法,就一定是调用super对象中的另一个兄弟方法吗?

因为子类已经覆盖了父类的方法,你在调用一个兄弟方法的时候,实际上,因为多态的存在,调用的是你的子类(代理类)的覆盖后的方法,而子类(代理类)的方法,是已经实现了拦截的方法。所以,这个时候,@transactional注解,是会生效的。

猜你喜欢

转载自blog.csdn.net/qq_31142553/article/details/81781037
今日推荐