cglib动态代理 | 拦截器

简介: cglib动态代理 | 拦截器

一、代理方法长什么样

代码示例:

//被代理类
class UserService {
  //方法必须能被重写,不能被final修饰
    public void test() {
        System.out.println("调用test方法了...");
    }
}
//拦截器(方法增强)
class MyApiInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("被代理方法执行前"); // 此处可以做一些操作
        Object result = proxy.invokeSuper(obj, args);//执行被代理方法
        System.out.println("被代理方法执行后" );  // 方法调用之后也可以进行一些操作
        return result;
    }
}
//测试
public class TestCglib {
    public static void main(String[] args) {
    //生成一个增强器
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(UserService.class); //设置要代理的类
        enhancer.setCallback(new MyApiInterceptor()); //设置回调的拦截器
        // 创建代理对象
        Person person=enhancer.create();
        person.test();
    }
}

  刚开始接触动态代理,设想的代理方法是如下的样子,是不是很简单粗暴,这么想是不是也挺合理。

  其实代理方法长这样:

  下面的test方法就是生成的代理方法,其中没有我们写的增强代码,也没有用super.test()去调用被代理方法,而是先获得一个拦截器,然后执行intercept()方法。

既然代理类是运行时自动生成的,为什么不直接把增强代码粘到代理方法中?

  行,但是不优雅。

  拦截器提供了一种可插拔的方式,使增强逻辑与目标方法解耦,能够灵活地对代理逻辑进行配置和管理。

  看看拦截器是如何起作用的。

二、代理方法逻辑

  从上面的例子看,我们调用代理对象的test方法,是如何去执行拦截器【MyApiInterceptor类】中的逻辑呢?

  这要看代理类重写的test方法做了写什么:

 从程序执行的结果上看,图上MethodInterceptor的实现类就是我们自定义的MyApiInterceptor,这里需要说明一下intercept方法的四个参数都是什么:


参数1:代理类对象

参数2:被代理类的方法对象(Method类型对象)

参数3:方法入参(Object[])

参数4:代理类的方法对象(MethodProxy类型对象)

  代理方法如何得到我们自定义的MyApiInterceptor对象?

MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;

 上面是test()方法的第一句代码,其中的(CGLIB$CALLBACK_0)属性是MethodInterceptor类型的,自定义的MyApiInterceptor正好实现了MethodInterceptor接口,这里明显是使用了里式替换。


 看哪里给(CGLIBC A L L B A C K 0 )属性赋值了,可以找到构造函数中挑中了【 C G L I B CALLBACK_0)属性赋值了,可以找到构造函数中挑中了【CGLIBCALLBACK0)属性赋值了,可以找到构造函数中挑中了【CGLIBBIND_CALLBACKS方法】,内容如下:

  //代理类构造函数
    public UserService$$EnhancerByCGLIB$$9391ced0() {
        CGLIB$BIND_CALLBACKS(this);
    }

 现在我们需要知道什么时候在缓存(CGLIB$THREAD_CALLBACKS属性)中存了自定义的MyApiInterceptor对象。


  在代理类中只找到一个静态方法【CGLIB$SET_THREAD_CALLBACKS】给上述属性赋值了,没有在本类中看到谁调用了这个方法。

    public static void CGLIB$SET_THREAD_CALLBACKS(Callback[] var0) {
        CGLIB$THREAD_CALLBACKS.set(var0);
    }

  所以我们要知道,是谁在什么地方调用了静态方法【CGLIB$SET_THREAD_CALLBACKS】

三、代理对象初始化过程

  从demo中看出,创建代理对象是通过enhancer.create();创建的,需要从【Enhancer 类】的【create方法】开始抽丝剥茧找到真相。看个源码和破案一样。

    //生成一个增强器
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(UserService.class); //设置要代理的类
        enhancer.setCallback(new MyApiInterceptor()); //设置回调的拦截器
        // 创建代理对象
        Person person=enhancer.create();

  方法【createUsingReflection】的第一句代码调用了方法【setThreadCallbacks】,并把代理类的Class对象传给了它。这个方法名的意思就是给ThreadCallbacks赋值,下图看该方法逻辑

 这里确定方法名SET_THREAD_CALLBACKS_NAME就是代理类中的静态方法【CGLIB$SET_THREAD_CALLBACKS】。另外因为是静态方法,反射调用时不用传递代理类对象,传个null就可以。



 标题2中我们的问题我们在这里就可以揭晓。

 是谁在什么时候调用了静态方法【CGLIBS E T T H R E A D C A L L B A C K S 】,给( C G L I B SET_THREAD_CALLBACKS】,给(CGLIBSETTHREADCALLBACKS】,给(CGLIBTHREAD_CALLBACKS属性)中存了自定义的MyApiInterceptor对象?


 who:Enhancer对象

 when:在创建了代理类之后,马上要生成代理类对象之前

四、总结

 CGLIB拦截器的作用主要有以下几个方面:


增加额外的逻辑:

 拦截器可以在目标方法执行前后,或者在方法执行过程中插入额外的逻辑。例如,可以在方法调用前进行权限检查、日志记录等操作,或者在方法调用后进行结果处理、异常处理等操作。通过拦截器,可以在不修改目标类的情况下,增加额外的功能。


实现横切关注点的分离:

 拦截器可以将与核心业务逻辑无关的横切关注点(cross-cuttingconcern)与核心业务逻辑分离。横切关注点包括日志记录、性能统计、事务管理等,这些功能可以通过拦截器统一管理,而不需要在每个目标方法中重复编写代码。


实现代理的灵活配置和管理:

 拦截器提供了一种可插拔的方式,使得增强逻辑可以与目标方法解耦,方便对代理逻辑进行配置和管理。通过拦截器,可以动态地添加、删除或修改代理逻辑,而无需修改目标类的源代码。


 CGLIB拦截器的作用是在代理类中插入增强逻辑,实现与目标方法的拦截、预处理和后处理操作,同时实现了横切关注点的分离和代理的灵活配置。它是CGLIB实现动态代理的重要组成部分,提供了一种强大的方式来扩展和定制代理类的行为。


相关文章
|
7月前
|
设计模式 Java
JDK动态代理
JDK动态代理
|
缓存 Java
探索Java动态代理:深入了解CGLib
了解什么是CGLib,它如何实现动态代理和代码增强,以及它与Java标准动态代理的比较。
678 0
|
Java 测试技术 Spring
动态代理:Cglib原理讲解
动态代理:Cglib原理讲解
150 1
jdk动态代理和cglb动态代理
jdk动态代理和cglb动态代理
|
Java Spring
jdk动态代理和cglib动态代理
只有聪明人才能看见的简介~( ̄▽ ̄~)~
91 0
jdk动态代理和cglib动态代理
|
Java Spring
手动实现aop使用的动态代理和cglib代理
spring的aop使用的是动态代理和cglib代理,在对象有实现接口的情况下使用动态代理,没有实现接口的情况下使用cglib代理。 cglib代理是继承目标对象来创建代理,所以目标对象不能使用final修饰。
|
Java
AOP(JDK动态代理实现)
采用JDK动态代理实现AOP必须要使代理类和被代理类实现同一个接口
102 0
AOP(JDK动态代理实现)
|
Java 索引
jdk动态代理和cglib动态代理的原理分析(下)
jdk动态代理和cglib动态代理的原理分析(下)
228 0
jdk动态代理和cglib动态代理的原理分析(下)
|
设计模式 Java 索引
jdk动态代理和cglib动态代理的原理分析(上)
jdk动态代理和cglib动态代理的原理分析(上)
jdk动态代理和cglib动态代理的原理分析(上)
|
存储 Java 关系型数据库
Java动态代理之一CGLIB详解
Java动态代理之一CGLIB详解
413 0
Java动态代理之一CGLIB详解