【代理】【七】代理源码解析-Cglib代理-为什么Spring中的代理方法互相调用 AOP 会失效,而原生的 Cglib 方法互相调用是会走增强的呢?
1 前言
今天我们来看个问题,我看源码的时候产生的困惑,就是我们都知道SpringAOP 我们方法中调用第二个方法,第二个方法不会走增强的逻辑,而原生的 Cglib 方法互相调用是会走增强的呢?我们看下现象:
1.1 原生 Cglib 方法互相调用
public class UserServiceImpl { private String name; public void say() { System.out.println("111"); say2(); } public void say2() { System.out.println("222"); } } public static void main(String[] args) { // 设置代理文件输出位置 System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "./code"); // 创建 cglib 代理类的核心对象 Enhancer enhancer = new Enhancer(); // 设置要创建代理的类 enhancer.setSuperclass(UserServiceImpl.class); // 跟 JDK 代理一样,增强的逻辑 enhancer.setCallback(new MyMethodInterceptor()); // 创建代理,并调用 UserServiceImpl userService = (UserServiceImpl) enhancer.create(); userService.say(); }
1.2 SpringAOP 方法互相调用
public class A { public void say() { System.out.println("111"); this.haha(); } public void haha() { System.out.println("222"); } } @Test public void testFactoryBean() { System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "./code"); ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("/spring/spring-alias.xml"); A a = applicationContext.getBean("a", A.class); a.say(); }
是不是,看见没我们的Spring 第二个方法是不会走增强的,那么我们来看下为什么。
2 原生的为什么方法调用可以增强
我上节分析 Cglib 产生的类文件的执行过程,其实已经说过为什么它可以增强,主要的就是因为自始至终我们的对象都是代理对象自己,所以它调用自己的第二个方法也是会走增强的,我们回顾下过程:
3 Spring 为什么方法内部调用不会走增强
那么我们来看下Spring的为什么不会走增强,那首先我们得看下代理是怎么创建出来的,具体的创建过程我在讲AOP的时候都分析过了,我们这里简单看下哈:
3.1 创建代理
3.2 执行方法
当我们代理类执行第一个方法的时候,进入到这里的增强:
看见了吧,也就是说代理类的方法执行的时候,进入增强逻辑,当执行目标方法的时候,传的是我们被代理类的对象自己,所以么自己调自己就不会走增强了。
4 小结
好,本节解决了我们的疑惑看了下为什么Spring的方法调用增强不生效的道理,有理解不对的地方欢迎指正哈。