• 实现Java基于类的代理方式 - CGLIB动态代理(动态代理篇 三)


    CGLIB(Code Generation Library)是一个基于类的动态代理库,它可以在运行时生成字节码来创建代理类。相比于JDK动态代理,CGLIB动态代理不需要接口,可以代理任意类。 CGLIB动态代理的实现原理是通过继承目标类来创建代理类,并重写目标类的方法。在代理类中,通过调用MethodInterceptor接口的方法来拦截目标方法的调用,并执行自定义的逻辑。

    1. maven工程引入依赖(或者普通工程引入jar包)

    1. <dependency>
    2. <groupId>cglibgroupId>
    3. <artifactId>cglib-nodepartifactId>
    4. <version>3.3.0version>
    5. dependency>

    2. 设计目标类,实现功能

    1. //接口
    2. public interface UserService {
    3. void addUser(String name);
    4. void deleteUser(String name);
    5. }
    1. //目标类和方法
    2. public class UserServiceImpl implements UserService {
    3. @Override
    4. public void addUser(String username) {
    5. System.out.println("添加的用户为: " + username);
    6. }
    7. @Override
    8. public void deleteUser(String username) {
    9. System.out.println("删除的用户为: " + username);
    10. }
    11. }

    3. 创建一个MethodInterceptor的实现类,用于拦截目标方法的调用并添加额外的逻辑。

    1. //拦截目标方法的类(也就是拦截器)
    2. public class LoggingInterceptor implements MethodInterceptor {
    3. /**
    4. * 重写intercept方法来拦截目标方法的调用,
    5. * 当调用被代理对象的方法时,intercept方法会被调用,并传入相应的参数.
    6. *
    7. * @param obj 被代理的对象
    8. * @param method 目标方法的反射对象
    9. * @param args 目标方法的参数数组
    10. * @param proxy MethodProxy对象,用于调用父类的方法
    11. * @return 目标方法的执行结果
    12. * @throws Throwable 异常(有代理就有反射,有反射就会出现异常的情况)
    13. */
    14. @Override
    15. public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
    16. System.out.println("-----前记录日志----");
    17. // 在执行目标方法之前记录日志
    18. System.out.println("准备执行的方法为: " + method.getName());
    19. // 调用代理对象的父类方法,即执行目标方法
    20. Object result = proxy.invokeSuper(obj, args);
    21. System.out.println("执行完成: " + method.getName());
    22. // 在执行目标方法之后记录日志
    23. System.out.println("-----后记录日志----");
    24. // 返回目标方法的执行结果
    25. return result;
    26. }
    27. }

    4. 使用CGLIB动态代理来创建代理对象并调用目标方法

    1. public class Main {
    2. public static void main(String[] args) {
    3. // 创建Enhancer对象(用于创建代理对象)
    4. Enhancer enhancer = new Enhancer();
    5. // 设置被增强类(被代理的类)
    6. enhancer.setSuperclass(UserServiceImpl.class);
    7. // 设置回调对象(回调对象负责拦截目标方法的调用并执行自定义逻辑)
    8. enhancer.setCallback(new LoggingInterceptor());
    9. // 创建真实代理对象
    10. UserService proxy = (UserService) enhancer.create();
    11. // 代理对象调用方法(调用方法时,会执行拦截器(回调对象)中的方法)
    12. proxy.addUser("小明");
    13. proxy.deleteUser("小米");
    14. }
    15. }

    5. 执行结果(达到增强的效果)

    GGLIB动态代理相对于JDK动态代理的优势

    1. 无需接口:JDK动态代理要求目标类实现接口,而CGLIB动态代理可以代理任意类,包括没有实现接口的类。这使得CGLIB更加灵活,可以代理更多类型的目标对象。

    2. 更高的性能:由于CGLIB是通过生成目标类的子类来实现代理,而JDK动态代理是通过实现目标类的接口来实现代理,所以CGLIB在性能方面通常比JDK动态代理更高效。CGLIB代理类的方法调用是通过方法继承实现的,而JDK动态代理需要通过反射调用目标方法,因此CGLIB的方法调用更快。

    3. 更强的功能:CGLIB可以代理目标类的所有方法,包括final方法、私有方法和静态方法等。而JDK动态代理只能代理接口的方法。这使得CGLIB在某些场景下更有优势,例如对于第三方类库或无法修改源代码的类的代理。

    4. 简单易用:相比于JDK动态代理,CGLIB的使用更加简单。在使用CGLIB时,我们只需要创建一个Enhancer对象,设置被代理类和回调对象,就可以创建代理对象。而JDK动态代理需要实现InvocationHandler接口,并通过Proxy类的静态方法创建代理对象

    上一篇:JDK动态代理

  • 相关阅读:
    读取windows日志
    【数据结构与算法】第一章 绪论 2-数据结构的基本概念
    Last Week in Milvus
    使用ffmpeg将一个目录下的mkv格式的视频文件转换成mp4格式
    TiDB Dashboard 实例性能分析 - 手动分析页面
    Vue3.0安装与构建项目
    Linux系统之安装uptime-kuma服务器监控面板
    如何关闭搜狗输入法的快捷键
    中高级Java程序员,你不得不掌握的基本功,挑战20k+
    【Scala专栏】字符串与集合
  • 原文地址:https://blog.csdn.net/DU9999999/article/details/133744530