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动态代理的基本方式。

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

相关推荐
葫芦和十三2 小时前
图解 MongoDB 21|选举与 failover:Primary 是怎么选出来的
后端·mongodb·agent
GetcharZp3 小时前
26k Star 开源内网穿透神器 NetBird,一分钟实现全球设备互联!
后端
考虑考虑3 小时前
Mybatis实现批量插入
java·后端·mybatis
咖啡八杯4 小时前
GoF设计模式——中介者模式
java·后端·spring·设计模式
lizhongxuan6 小时前
多Agent之间的区别
后端
青石路8 小时前
记一次多JDK版本问题的排查,一坑套一坑,差点没爬上来
java
杨充8 小时前
1.面向对象设计思想
后端
IT_陈寒9 小时前
Java的Date类又坑了我一次,改用时间戳真香
前端·人工智能·后端
systemPro9 小时前
2.6亿条设备数据,历史查询从超时到50ms,我做了什么
后端
要阿尔卑斯吗9 小时前
提示词优化启示:为什么“按顺序输出“比“关键度评分“更有效
后端