刚入手Spring时感觉还好,凭借学到的反射和注解还能大致推断出底层的实现流程,但到AOP这一块的时候就感觉很迷了,为什么我调用的方法返回值发生了改变,为什么自己new的又不会了。。。
后来了解到CGLIB这种技术才慢慢解开了我的疑惑,这也是代码为什么可以一致直吸引我的地方,因为她可以满足洒家的欲望(求知欲)
行了不bb了,上代码
首先是CGLIB的依赖
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
public class Test2 {
/*代理类需要实现MethodInterceptor接口并重写intercept方法*/
static class Test2Proxy implements MethodInterceptor {
@Override
/*参数1:被代理类实例,参数2:被拦截的方法,参数3:被拦截方法的参数列表,参数4:代理方法*/
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
/*调用被拦截的方法,此处不要用invoke方法,会被再次拦截一直递归直至栈堆溢出*/
Object o1 = methodProxy.invokeSuper(o,objects);
String s = "-------Before";
/*可以任意更改原方法的返回值*/
return o1+s;
}
}
static class Test2Proxy2 implements MethodInterceptor{
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
return methodProxy.invokeSuper(o,objects);
}
}
public String getHello(){
return "Hello";
}
public String getHello2(){
return "Hello2";
}
static void test(){
Enhancer enhancer = new Enhancer();
/*
设置被代理类
从各种命名中的super不难看出,动态代理类是被代理类的子类,
而拦截的方法也是对父类方法的重写
所以这也是为什么被final修饰的类和方法不能被代理的原因
*/
enhancer.setSuperclass(Test2.class);
/*设置单个代理类*/
enhancer.setCallback(new Test2Proxy2());
/*配置回调过滤器控制方法回调时使用的代理类*/
CallbackFilter cbf = method -> {
/*这种equals的使用(已知比未知)也算是一种良好的编程习惯,可以有效避免空指针*/
if("getHello2".equals(method.getName())){
return 1;
}
//这里返回的int是代表setCallbacks方法中传递的数组的索引,来决定使用哪一个代理类
return 0;
};
/*设置多个代理类对象,会使setCallback方法的配置失效*/
enhancer.setCallbacks(new Callback[]{new Test2Proxy(),new Test2Proxy2()});
/*设置拦截方法的过滤器*/
enhancer.setCallbackFilter(cbf);
/*创建代理类对象*/
Test2 t2 = (Test2) enhancer.create();
System.out.println(t2.getClass()+"\n"+t2.getHello()+"\n"+t2.getHello2());
}
public static void main(String[] args) {
test();
}
}
控制台:
确实,CGLIB比JDK动态代理功能更加强大
牛哔!