- CGLIB(code Generation Library),Code生成类库
- CGLIB 动态代理不限定是否具有接口,可以对任意操作进行增强
- CGLIB 动态代理不需要原始被代理对象,动态创建出新的代理对象
代理方法:
public class UserServiceCglibProxy {
public static UserService createUserServiceCglibProxy(Class clazz) {
// 在内存中创建字节码
Enhancer enhancer = new Enhancer();
// 创建对象 最后需要强转成UserService对象,只有父子类可以转,当前UserService是一个接口,只有设置字节码对象父类为UserServiceImpl实现类
enhancer.setSuperclass(clazz);
// 需要调用原始方法
enhancer.setCallback(new MethodInterceptor() {
@Override
//代理出来类的对象 //原始调用方法 //args // 代理方法,造出字节码中的方法
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
Object ret = methodProxy.invokeSuper(o, objects);
if(method.getName().equals("save")){
System.out.println("刮大白");
System.out.println("贴墙纸");
}
return ret;
}
});
return (UserService)enhancer.create();
}
}
启动方法
public class App {
public static void main(String[] args) {
UserService userService = UserServiceCglibProxy.createUserServiceCglibProxy(UserServiceImpl.class);
userService.save();
}
}
1、创建字节码对象Enhancer enhancer = new Enhancer();
2、应为最后需要返回类型为UserService对象,所以需要强转类型,强转类型必须是父子类,但是当前类(UserService是一个接口,无法转换),那么我们必须手动设置字节码的父类:enhancer.setSuperclass(clazz);需要传入父类字节码对象
3、增强方法必须得调用原始方法,在原始方法操作上调用方法。调用原始方法:enhancer.setCallback(需要参数new MethodInterceptor)
MethodInterceptor需要参数,使用匿名内部类,和JDK Proxy相似,规则:
intercept方法(Object o, Method method, Object[] objects, MethodProxy methodProxy):
参数1:代理出来类的对象
参数2:原始调用方法
参数3:args参数
参数4:代理方法,造出字节码中的方法
因为需要调用父类方法,而当前参数1是代理出来的对象,所以我们必须使用methodProxy.invokeSuper(o, objects); 代理出来的方法.invokerSuper调用父类的方法(就是原始方法)
ps:当前增强是对父类所有方法进行了增强,而我们执行时代理对象有两个操作:toString,hashCode,作用是为代理对象生成地址值,所以如果我们直接对增强方法,每次也会对这两个方法进行增强,导致多次运行增强方法。所以我们进行判断,对需要的方法进行增强