除了 JDK Dynamic Proxy 外,我们可以使用 CGLib 实现动态代理。与前者不同,CGLib 并不需要提供接口,可以直接对一个 Java 类进行代理,它的底层是通过继承被代理类实现代理的,所以被代理类不能被 fianl 关键字修饰

引入依赖

使用 CGLib 前需要引入相关依赖,示例代码如下所示:

  1. <dependency>
  2. <groupId>cglib</groupId>
  3. <artifactId>cglib</artifactId>
  4. <version>${cglib.version}</version> <!-- latest is 3.3.0 -->
  5. </dependency>

实现动态代理

被代理类声明如下所示:

  1. public class Greeting {
  2. public void hello(String name) {
  3. System.out.println("Hello " + name);
  4. }
  5. }

动态代理实现如下所示:

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 实现动态代理大致分为如下几个步骤:

  1. 创建一个 Enhancer 对象;
  2. 设置 super class,即被代理类;
  3. 设置回调方法;
  4. 创建 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 个子接口继承了该接口: MethodInterceptorNoOpLazyLoaderDisaptcherInvocationHandlerFixedValue 。上面的示例即传入了一个 MethodInterceptor 实现类,这些子接口通过名字就能明白其大概作用,具体使用时请参看源码注释,本文就不再过多赘述了。