在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动态代理的基本方式。
有好的建议,请在下方输入你的评论