Spring(九)CGLIB字节码增强

时间:2023-01-13 15:22:09

上篇文章说明了jdk动态代理。
在这里说一下cglib动态代理

说明

jdk动态代理和cglib动态代理的区别在于:

cglib没有接口(通过继承父类) 只有实现类。
采用字节码增强框架cglib,在运行时 创建目标的子类 ,从而对目标类进行增强。

下面通过一个案例来说明CGLIB动态代理
目标类
总共实现三个业务
添加用户信息(addUser) 更新用户信息(updateUser) 删除用户信息(deleteUser)

public class UserServiceImpl{

public void addUser() {
System.out.println("UserServiceDaoImpl addUser");
}

public void updateUser() {
System.out.println("UserServiceDaoImpl updateUser");
}


public void deleteUser() {
System.out.println("UserServiceDaoImpl deleteUser");
}

}

切面类
要添加在目标类方法前后的方法。

public class MyAspect {
//前方法
public void before(){
System.out.println("cglib_before");

}
//后方法
public void after(){
System.out.println("cglib_after");
}
}

工厂类
工厂类步骤如下:
1.目标类
2.切面类
3.代理类
3.1 核心类
3.2确定父类
3.3设置回调函数
而在设置回调函数里面和jdk动态代理类似
设置回调函数 MethodInterceptor接口等效于jdk invocationHandler接口
intercept()等效于jdk invoke()
intercept参数1 ,参数2,参数3 和invoke三个参数一样
参数4,methodProxy 方法代理
可以使用methodProxy.invokeSuper(proxy, args);来执行父类的方法

public class MyProxyFactory {
public static Object createUserService() {
//目标类
final UserServiceImpl userService = new UserServiceImpl();
//切面类
final MyAspect myAspect = new MyAspect();
//代理类 采用cglib 底层创建目标的子类
//核心类
Enhancer enhancer=new Enhancer();
//确定父类
enhancer.setSuperclass(UserServiceImpl.class);
/*
* 设置回调函数 MethodInterceptor接口等效于jdk invocationHandler接口
* intercept()等效于jdk invoke()
* 参数1 ,参数2,参数3 和invoke三个参数一样
* 参数4,methodProxy 方法代理
*/

enhancer.setCallback(new MethodInterceptor() {

@Override
public Object intercept(Object proxy, Method method, Object[] args,
MethodProxy methodProxy) throws Throwable {
//前方法
myAspect.before();
//执行目标类的方法
Object obj=method.invoke(userService, args);
//后方法
myAspect.after();
return obj;
}
});
Object proxy=enhancer.create();
return proxy;
}
}

运行结果:
Spring(九)CGLIB字节码增强