CGLIB(Code Generation Library)是一个基于类的动态代理库,它可以在运行时生成字节码来创建代理类。相比于JDK动态代理,CGLIB动态代理不需要接口,可以代理任意类。 CGLIB动态代理的实现原理是通过继承目标类来创建代理类,并重写目标类的方法。在代理类中,通过调用MethodInterceptor接口的方法来拦截目标方法的调用,并执行自定义的逻辑。
1. maven工程引入依赖(或者普通工程引入jar包)
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<version>3.3.0</version>
</dependency>
2. 设计目标类,实现功能
//接口
public interface UserService {
void addUser(String name);
void deleteUser(String name);
}
//目标类和方法
public class UserServiceImpl implements UserService {
@Override
public void addUser(String username) {
System.out.println("添加的用户为: " + username);
}
@Override
public void deleteUser(String username) {
System.out.println("删除的用户为: " + username);
}
}
3. 创建一个MethodInterceptor的实现类,用于拦截目标方法的调用并添加额外的逻辑。
//拦截目标方法的类(也就是拦截器)
public class LoggingInterceptor implements MethodInterceptor {
/**
* 重写intercept方法来拦截目标方法的调用,
* 当调用被代理对象的方法时,intercept方法会被调用,并传入相应的参数.
*
* @param obj 被代理的对象
* @param method 目标方法的反射对象
* @param args 目标方法的参数数组
* @param proxy MethodProxy对象,用于调用父类的方法
* @return 目标方法的执行结果
* @throws Throwable 异常(有代理就有反射,有反射就会出现异常的情况)
*/
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("-----前记录日志----");
// 在执行目标方法之前记录日志
System.out.println("准备执行的方法为: " + method.getName());
// 调用代理对象的父类方法,即执行目标方法
Object result = proxy.invokeSuper(obj, args);
System.out.println("执行完成: " + method.getName());
// 在执行目标方法之后记录日志
System.out.println("-----后记录日志----");
// 返回目标方法的执行结果
return result;
}
}
4. 使用CGLIB动态代理来创建代理对象并调用目标方法
public class Main {
public static void main(String[] args) {
// 创建Enhancer对象(用于创建代理对象)
Enhancer enhancer = new Enhancer();
// 设置被增强类(被代理的类)
enhancer.setSuperclass(UserServiceImpl.class);
// 设置回调对象(回调对象负责拦截目标方法的调用并执行自定义逻辑)
enhancer.setCallback(new LoggingInterceptor());
// 创建真实代理对象
UserService proxy = (UserService) enhancer.create();
// 代理对象调用方法(调用方法时,会执行拦截器(回调对象)中的方法)
proxy.addUser("小明");
proxy.deleteUser("小米");
}
}
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动态代理