除了 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 实现类,这些子接口通过名字就能明白其大概作用,具体使用时请参看源码注释,本文就不再过多赘述了。