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

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

相关推荐
2301_8153577015 分钟前
Spring框架--IOC技术
java·后端·spring
yb0os116 分钟前
手写一个简单的线程池
java·开发语言·数据库·计算机·线程池·juc
李景琰31 分钟前
分布式事务之Seata
java·分布式
加什么瓦33 分钟前
JVM——内存模型
java·开发语言·jvm
观音山保我别报错34 分钟前
JVM 的垃圾回收机制 GC
java·开发语言·jvm
走过冬季42 分钟前
Java常用数据结构底层实现原理及应用场景
java·开发语言·数据结构
XIMCoCo43 分钟前
C++ 实现二叉树的后序遍历与中序遍历构建及层次遍历输出
java·开发语言·c++
Java 技术轻分享1 小时前
Java 多线程编程:核心原理、同步机制与高并发详解
java·开发语言
0x7CF5 小时前
SetThrowSegvLongjmpSEHFilter错误和myFuncInitialize 崩溃
java·linux·算法
diving deep9 小时前
springboot集成日志配置文件
java·spring boot·后端·logback