首页 > 编程语言 >【代理】【七】代理源码解析-Cglib代理-为什么Spring中的代理方法互相调用 AOP 会失效,而原生的 Cglib 方法互相调用是会走增强的呢?

【代理】【七】代理源码解析-Cglib代理-为什么Spring中的代理方法互相调用 AOP 会失效,而原生的 Cglib 方法互相调用是会走增强的呢?

时间:2023-03-05 16:44:06浏览次数:37  
标签:增强 调用 代理 Cglib 方法 public

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

标签:增强,调用,代理,Cglib,方法,public
From: https://www.cnblogs.com/kukuxjx/p/17180749.html

相关文章

  • go的表达式调用编译器不会进行自动转换 未完成
    packagemainimport( "fmt")typeTstruct{ aint}func(tT)Get()int{ returnt.a}func(t*T)Set(iint){ t.a=i}//表达式`T.Get`和`(*T).Set......
  • C#代理模式
    定义:代理模式(Proxy),为其他对象提供一种代理以控制对这个对象的访问应用:1.远程代理,也就是为一个对象在不同的地址空间提供局部代表,这样可以隐藏一个对象存在于不同地址空......
  • ES6-ES11 生成器函数声明与调用
    原视频<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width,initial-scale=1.0"><title......
  • eyoucms 首页以及列表页内容调用标题、关键词、描述
    1、首页调用标题、关键词、描述123<title>{eyou:global name='web_title' /}</title><metaname="description" content="{eyou:globalname='web_descr......
  • eyoucms 调用搜索代码
    下方是搜索代码,不管首页或者列表页以及内容页都已经使用。123456789{eyou:searchformtype='default'}    <formmethod="get" action="{$field......
  • Docker配置代理
    DockerPull配置代理用docker拉取halohub/halo的时候特别慢,使用国内docker镜像也不行,可以通过设置代理来解决在执行dockerpull时,是由守护进程dockerd来执行。因此,代理需......
  • 【代理】【六】代理源码解析-Cglib代理-代理文件执行分析
    1 前言上节我们简单看了Enhancer的generateClass和 firstInstance,两个方法的内容也就是创建代理以及生成代理对象的内容,这节我们结合实际生成的文件了解一下代理......
  • C#使用WinExec调用exe程序
    添加引用usingSystem.Runtime.InteropServices;//调用外部的DLL 定义DLL[DllImport("kernel32.dll")]publicstaticexternintWinExec(stringprogramPath,......
  • IPIDEA教你怎么选择适合TikTok的代理IP?
    要说到现在最火的自媒体平台,不得不提的就是短视频流量霸主TikTok,无论是国内版的抖音,还是国际版的TikTok,都是新一代年轻人中的流行趋势。不管是个体还是企业,都希望能抓住Ti......
  • Android JNI 调用
    1.Android Studio创建native项目   对项目进行解释cmake_minimum_required(VERSION3.10.2)#Declaresandnamestheproject.project("jnitest")#Create......