简介
在公司分享会上,提到了cglib生成动态生成代理类。cglib跟jdk动态代理最大的区别就是,jdk的动态代理要求被代理对象必须有接口,对那些没有接口的普通bean,jdk动态代理一点办法都没有,而cglib可以为没有接口的bean生成代理对象。其实cglib是使用ASM来操作字节码重新生成新的类,我么也可以使用ASM直接直接生成操作字节码,但是他需要对java字节码的格式有足够的了解。
API
Enhancer
Enhancer是cglib最常用的一个类,Enhancer创建一个被代理对象的子类并拦截所有的方法的调用,和jdk的proxy很类似,由于Enhancer是创建被代理对象的子类,所以Enhancer不能拦截final方法也不能代理final类
public class CGlibTestClass {
public void test1(){
System.out.println("hello world test1");
}
public void test2() {
System.out.println("hello world test2");
}
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(CGlibTestClass.class);
enhancer.setCallback((MethodInterceptor) (obj, method, args1, proxy) -> {
System.out.println("before method run...");
Object result = proxy.invokeSuper(obj, args1);
System.out.println("after method run...");
return result;
});
CGlibTestClass sample = (CGlibTestClass) enhancer.create();
sample.test1();
sample.test2();
}
}
其结果如下:
before method run...
hello world test1
after method run...
before method run...
hello world test2
after method run...
MethodInterceptor拦截所有的方法,如果想只拦截特定的方法可以使用CallBackFilter
public class TestCallBackFilter {
public void test1() {
System.out.println("test1");
}
public void test2() {
System.out.println("test2");
}
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
CallbackHelper callbackHelper = new CallbackHelper(TestCallBackFilter.class, new Class[0]) {
@Override
protected Object getCallback(Method method) {
if (method.getName().equals("test1")) {
return (MethodInterceptor) (obj, invokeMethod, args1, proxy) -> {
System.out.println("before method run...");
Object result = proxy.invokeSuper(obj, args1);
System.out.println("after method run...");
return result;
};
} else {
return NoOp.INSTANCE;
}
}
};
enhancer.setSuperclass(TestCallBackFilter.class);
enhancer.setCallbackFilter(callbackHelper);
enhancer.setCallbacks(callbackHelper.getCallbacks());
TestCallBackFilter proxy = (TestCallBackFilter) enhancer.create();
proxy.test1();
proxy.test2();
}
}
运行结果如下:
before method run...
test1
after method run...
test2