文章目录
动态代理常用有三: JDK代理, cglib代理, javaassistant代理. 这里demo一下 cglib代理…
cglib 是 jdk代理的补充, 最大的区别在于能够针对一个无接口的类实现代理.
本质是针对被代理类生成一个功能增强的子类. 因此, private 方法, final类,都是不能被代理的.
来看demo:
public class CglibProxy implements MethodInterceptor {
private Enhancer enhancer = new Enhancer();
/**
* All generated proxied methods call this method instead of the original method.
* The original method may either be invoked by normal reflection using the Method object,
* or by using the MethodProxy (faster).
*
* @param obj "this", the enhanced object
* @param method intercepted Method
* @param args argument array; primitive types are wrapped
* @param proxy used to invoke super (non-intercepted method); may be called
* as many times as needed
**/
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("I am before method invocation" + this.getClass().getName());
Object result = proxy.invokeSuper(obj, args);
System.out.println("I am after method invocation" + this.getClass().getName());
return result;
}
public Object getProxy(Class clazz) {
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);// 设置cb对象, 就是这个 MethodInterceptor
return enhancer.create();// 通过bytecode技术动态创建子类实例
}
}
class CglibProxyTest {
public static void main(String[] args) {
CglibProxy cglibProxy = new CglibProxy();
CglibProxyTest proxy = (CglibProxyTest) cglibProxy.getProxy(CglibProxyTest.class);
String method = proxy.method("1024");
System.out.println(method);
}
public String method(String str) {
System.out.println(str);
return "CglibProxyTest.method : " + str;
}
}
使用cglib代理, 关键需要理解这里的 MethodInterceptor.intercept
方法的各个参数. MethodInterceptor
是对被代理类的方法的增强.
Enhancer
就是代理类的生成器,它的java doc有这么一段话:
The original and most general callback type is the MethodInterceptor, which in AOP terms enables “around advice”–that is, you can invoke custom code both before and after the invocation of the “super” method. In addition you can modify the arguments before calling the super method, or not call it at all.
Although MethodInterceptor is generic enough to meet any interception need, it is often overkill. For simplicity and performance, additional specialized callback types, such as LazyLoader are also available. Often a single callback will be used per enhanced class, but you can control which callback is used on a per-method basis with a CallbackFilter.
The most common uses of this class are embodied in the static helper methods. For advanced needs, such as customizing the ClassLoader to use, you should create a new instance of Enhancer. Other classes within CGLIB follow a similar pattern.
这段话指出了三点:
MethodInterceptor
就是方法拦截器, 类似AOP中的around advice
MethodInterceptor
用起来不爽的话,还有LazyLoader
这些Enhancer
的子类可以使用; 同时还有CallbackFilter
来控制什么 方法需要代理,什么不需要.这个特性很有用, 当我们去代理一个类,未必希望所有方法都被拦截.Enhancer
在静态工具方法中用得多. 但不同Classloader,应该有自己的Enhancer
.
另外:
上面的demo ,在getProxy()
方法中,我们直接 给Enhancer
设置了多个属性,但多线程的情况下,未必能正常跑.