SpringBoot(三十)Springboot使用CGLIB动态代理

在Spring Boot中,使用CGLIB进行动态代理通常是为了创建目标类的代理对象,以便在不修改原始代码的情况下增加额外的行为。

比如增加方法的日志记录、性能监控、事务管理等。

以下是一个使用CGLIB动态代理的简单示例:

不需要添加任何依赖,Springboot默认的动态代理就是CGLIB。

一:创建一个需要被代理的类:

CGLIB动态代理不需要类一定要实现接口,所以我这里直接创建一个类即可,当然,你要想先创建接口,在做一个实现类也是可以的。看你自己的习惯。

typescript 复制代码
package com.modules.controller.test;

public class IndexImpl
{
    public void test(int num,String search)
    {
        System.out.println("num:" + num);
        System.out.println("search:" + search);
        System.out.println("进入了IndexImpl中的test方法!");
    }

    public String sayHello(String name)
    {
        return "Hello, " + name + "!";
    }
}

二:使用CGLIB创建代理类:

这个就没什么好讲的了,跟我们代理模式里边讲的是一样的,里边有注释。参照即可。

kotlin 复制代码
package com.modules.controller.fontend;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;
import java.util.Arrays;

public class CglibProxy implements MethodInterceptor {

    private Object target;

    /**
     * CGLIB动态代理类
     */

    public Object getProxyObject(Object target)
    {
        this.target = target;
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(this.target.getClass());
        enhancer.setCallback(this);
        return enhancer.create();
    }

    /**
     * 代理对象执行的所有方法都会走这个方法
     *
     * @param object           被代理的对象
     * @param method      被代理对象需要执行的方法
     * @param args     被代理对象需要执行的方法 参数
     * @param proxy 触发父类的方法对象
     * @return 被代理对象需要执行的方法 返回值
     * @throws Throwable 抛出的异常信息
     */
    @Override
    public Object intercept(Object object, Method method, Object[] args, MethodProxy proxy) throws Throwable
    {
        System.out.println("Before method execution: " + method.getName());
        System.out.println(Arrays.stream(args).iterator().next().getClass().getName());
        System.out.println(proxy.getSuperIndex());
        System.out.println(proxy.getSuperName());
        System.out.println(proxy.getSignature().getName());
        System.out.println("After method execution: " + method.getName());

        System.out.println("Before method execution: " + method.getName());
        Object result = proxy.invokeSuper(object, args);
        System.out.println("After method execution: " + method.getName());
        return result;
    }
}

三:使用代理类:

测试一下:

ini 复制代码
public static void main(String[] args)
{
    CglibProxy cglibProxy = new CglibProxy();
    // 获取代理对象
    IndexImpl proxyIndexService = (IndexImpl) cglibProxy.getProxyObject(new IndexImpl());
    // 执行代理方法
    proxyIndexService.test(1,"");

    IndexImpl proxyHelloService = (IndexImpl) cglibProxy.getProxyObject(new IndexImpl());
    String result = proxyHelloService.sayHello("World");
    System.out.println(result);
}

运行代码,控制台输出:

bash 复制代码
Before method execution: test
java.lang.Integer
15
CGLIB$test$0
test
After method execution: test
Before method execution: test
num:1
search:
进入了IndexImpl中的test方法!
After method execution: test
Before method execution: sayHello
java.lang.String
12
CGLIB$sayHello$1
sayHello
After method execution: sayHello
Before method execution: sayHello
After method execution: sayHello
Hello, World!

在这个例子中,CglibProxy类实现了MethodInterceptor接口,并重写了intercept方法。当你调用代理对象的方法时,intercept方法会被调用,并在其中可以添加自定义的逻辑。在getProxyObject方法中,我们使用Enhancer来创建代理对象。

以上代码仅作为使用CGLIB的简单示例,实际项目中可能需要更复杂的逻辑处理。

四:CGLIB优缺点:

1.优点

JDK实现动态代理需要实现类通过接口定义业务方法,对于没有接口的类,如何实现动态代理呢,这就需要CGLb了。

另一个优点是Cglib动态代理比使用java反射的JDK动态代理要快(Cglib的FastClass机制)。

2.缺点

对于被代理类中的final方法,无法进行代理,因为子类中无法重写final函数。

CGLib创建的动态代理对象性能比JDK创建的动态代理对象的性能高不少,但是CGLIB在创建代理对象时所花费的时间却比JDK多得多,所以对于单例的对象,因为无需频繁创建对象,用CGLIB合适,反之,使用JDK方式要更为合适一些。

同时,由于CGLIB由于是采用动态创建子类的方法,对于final方法,无法进行代理。

以上大概就是Springboot使用CGLIB动态代理的基本方式。

有好的建议,请在下方输入你的评论

相关推荐
程序员爱钓鱼1 小时前
Python编程实战 · 基础入门篇 | 元组(tuple)
后端·python·ipython
程序员爱钓鱼1 小时前
Python编程实战 · 基础入门篇 | 列表(list)
后端·python·ipython
青云交3 小时前
Java 大视界 -- 基于 Java 的大数据机器学习模型在图像识别中的迁移学习与模型优化
java·大数据·迁移学习·图像识别·模型优化·deeplearning4j·机器学习模型
2501_909800813 小时前
Java 集合框架之 Set 接口
java·set接口
断剑zou天涯4 小时前
【算法笔记】暴力递归尝试
java·笔记·算法
Nobody_Cares5 小时前
JWT令牌
java
沐浴露z5 小时前
Kafka入门:基础架构讲解,安装与使用
java·分布式·kafka
神秘的土鸡5 小时前
从数据仓库到数据中台再到数据飞轮:我的数据技术成长之路
java·服务器·aigc·数据库架构·1024程序员节
vir025 小时前
P1928 外星密码(dfs)
java·数据结构·算法·深度优先·1024程序员节
摇滚侠5 小时前
全面掌握PostgreSQL关系型数据库,备份和恢复,笔记46和笔记47
java·数据库·笔记·postgresql·1024程序员节