除了 JDK Dynamic Proxy 外,我们可以使用 CGLib 实现动态代理。与前者不同,CGLib 并不需要提供接口,可以直接对一个 Java 类进行代理,它的底层是通过继承被代理类实现代理的,所以被代理类不能被 fianl 关键字修饰。
引入依赖
使用 CGLib 前需要引入相关依赖,示例代码如下所示:
<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>${cglib.version}</version> <!-- latest is 3.3.0 --></dependency>
实现动态代理
被代理类声明如下所示:
public class Greeting {public void hello(String name) {System.out.println("Hello " + name);}}
动态代理实现如下所示:
Enhancer enhancer = new Enhancer(); // create an Enhancer instance
enhancer.setSuperclass(PersonService.class); // set super class
enhancer.setCallback(new MethodInterceptor() { // set callback
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("invoke before");
Object invokeSuper = proxy.invokeSuper(obj, args); // invoke super
System.out.println("invoke after");
return invokeSuper;
}
});
Greeting greeting = (Greeting) enhancer.create(); // create proxy
greeting.hello("Alice"); // invoke method
执行结果如下所示:
invoke before
Hello Alice
invoke after
使用 CGLib 实现动态代理大致分为如下几个步骤:
- 创建一个
Enhancer对象; - 设置 super class,即被代理类;
- 设置回调方法;
- 创建 proxy 并调用。
其中,最重要的是第 3 步 —— 设置回调参数, setCallback(Callback callback) 方法需要传入一个 Callback 类型参数,该接口声明如下所示:
package net.sf.cglib.proxy;
/**
* All callback interfaces used by Enhancer extend this interface.
* @see MethodInterceptor
* @see NoOp
* @see LazyLoader
* @see Dispatcher
* @see InvocationHandler
* @see FixedValue
*/
public interface Callback {}
可见 Callback 接口并未声明任何方法,但有 6 个子接口继承了该接口: MethodInterceptor 、 NoOp 、 LazyLoader 、 Disaptcher 、 InvocationHandler 、 FixedValue 。上面的示例即传入了一个 MethodInterceptor 实现类,这些子接口通过名字就能明白其大概作用,具体使用时请参看源码注释,本文就不再过多赘述了。
