【代理】【七】代理源码解析-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的方法调用增强不生效的道理,有理解不对的地方欢迎指正哈。

posted @ 2023-03-05 16:37  酷酷-  阅读(126)  评论(0编辑  收藏  举报