Spring 动态代理时提供了 JDK 代理和 CGLIB 两种方式,一般而言,代理的目标是接口时 AOP 使用 JDK 代理来实现,CGLIB 则负责对类进行代理,两种代理方法结合使用。
一、JDK代理代码实现
package com.nineya.spring.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
interface JdkTargetInterface {
    String test(String str);
}
class JdkTargetObject implements JdkTargetInterface {
    @Override
    public String test(String str) {
        System.out.println("被代理函数执行:" + str);
        return "被代理函数的返回结果";
    }
}
class JdkProxyHandler implements InvocationHandler {
    private Object target;
    public JdkProxyHandler() {
    }
    public JdkProxyHandler(Object target) {
        this.target = target;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("代理函数执行:" + method);
        if (target == null) {
            return "代理函数的返回结果";
        }
        return method.invoke(target, args);
    }
}
public class JdkProxyMain {
    private static void proxyInterface() {
        // 创建代理类
        JdkTargetInterface proxyTargetInterface = (JdkTargetInterface) Proxy.newProxyInstance(
                JdkProxyMain.class.getClassLoader(), new Class[]{JdkTargetInterface.class}, new JdkProxyHandler());
        String result = proxyTargetInterface.test("这是请求参数");
        System.out.println("执行结果:" + result);
    }
    private static void proxyObject() {
        // 被代理对象
        JdkTargetObject targetObject = new JdkTargetObject();
        // 创建代理类
        JdkTargetInterface proxyTargetInterface = (JdkTargetInterface) Proxy.newProxyInstance(
                JdkProxyMain.class.getClassLoader(), new Class[]{JdkTargetInterface.class}, new JdkProxyHandler(targetObject));
        String result = proxyTargetInterface.test("这是请求参数");
        System.out.println("执行结果:" + result);
    }
    public static void main(String[] args) {
        System.out.println("## Jdk 代理接口");
        proxyInterface();
        System.out.println("## Jdk 代理对象");
        proxyObject();
    }
}
二、CGLIB代理代码实现
package com.nineya.spring.proxy;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
interface CglibTargetInterface {
    String test(String str);
}
class CglibTargetObject {
    public String test(String str) {
        System.out.println("被代理函数执行:" + str);
        return "被代理函数的返回结果";
    }
}
/**
 * cglib代理处理类
 */
class CglibProxyHandler implements MethodInterceptor {
    private Object target;
    public CglibProxyHandler() {
    }
    public CglibProxyHandler(Object target){
        this.target = target;
    }
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("代理函数执行:" + method);
        if (target == null) {
            return "代理函数的返回结果";
        }
        return methodProxy.invoke(target, objects);
    }
}
public class CglibProxyMain {
    private static void proxyObject() {
        // 被代理对象
        CglibTargetObject targetObject = new CglibTargetObject();
        Enhancer enhancer = new Enhancer();
        // 被代理的类
        enhancer.setSuperclass(CglibTargetObject.class);
        // cglib代理处理类
        enhancer.setCallback(new CglibProxyHandler(targetObject));
        // 取得代理后的对象
        CglibTargetObject proxyTargetObject = (CglibTargetObject) enhancer.create();
        String result = proxyTargetObject.test("这是请求参数");
        System.out.println("执行结果:" + result);
    }
    
    private static void proxyInterface() {
        Enhancer enhancer = new Enhancer();
        // 被代理的类
        enhancer.setSuperclass(CglibTargetInterface.class);
        // cglib代理处理类
        enhancer.setCallback(new CglibProxyHandler());
        // 取得代理后的对象
        CglibTargetInterface proxyTargetObject = (CglibTargetInterface) enhancer.create();
        String result = proxyTargetObject.test("这是请求参数");
        System.out.println("执行结果:" + result);
    }
    
    public static void main(String[] args) {
        System.out.println("## CGLIB 代理接口");
        proxyInterface();
        System.out.println("## CGLIB 代理对象");
        proxyObject();
    }
}
三、对比
- 
CGLIB需要导入第三方依赖包,JDK代理可以直接实现。 - 
通过观察上面两份代码可以看到,
CGLIB可以直接对接口和类进行代理,而JDK代理方式则只能对接口进行处理,要代理的实现类也必须要实现接口。JDK代理如果对非接口类进行处理将抛出异常。Exception in thread "main" java.lang.IllegalArgumentException: com.nineya.spring.proxy.JdkTargetObject is not an interface at java.lang.reflect.Proxy$ProxyClassFactory.apply(Proxy.java:590) at java.lang.reflect.Proxy$ProxyClassFactory.apply(Proxy.java:557) at java.lang.reflect.WeakCache$Factory.get(WeakCache.java:230) at java.lang.reflect.WeakCache.get(WeakCache.java:127) at java.lang.reflect.Proxy.getProxyClass0(Proxy.java:419) at java.lang.reflect.Proxy.newProxyInstance(Proxy.java:719) at com.nineya.spring.proxy.JdkProxyMain.proxyInterface(JdkProxyMain.java:43) at com.nineya.spring.proxy.JdkProxyMain.main(JdkProxyMain.java:63)CGLIB的目标类如果被final关键字修饰也会抛出异常,这是由于CGLIB通过创建目标类的子类来实现直接对目标类的代理。不直接对类进行代理的JDK代理方式不受影响。Exception in thread "main" java.lang.IllegalArgumentException: Cannot subclass final class com.nineya.spring.proxy.CglibTargetObject at org.springframework.cglib.proxy.Enhancer.generateClass(Enhancer.java:660) at org.springframework.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25) at org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:358) at org.springframework.cglib.proxy.Enhancer.generate(Enhancer.java:585) at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:110) at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData$3.apply(AbstractClassGenerator.java:108) at org.springframework.cglib.core.internal.LoadingCache$2.call(LoadingCache.java:54) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at org.springframework.cglib.core.internal.LoadingCache.createEntry(LoadingCache.java:61) at org.springframework.cglib.core.internal.LoadingCache.get(LoadingCache.java:34) at org.springframework.cglib.core.AbstractClassGenerator$ClassLoaderData.get(AbstractClassGenerator.java:134) at org.springframework.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:319) at org.springframework.cglib.proxy.Enhancer.createHelper(Enhancer.java:572) at org.springframework.cglib.proxy.Enhancer.create(Enhancer.java:387) at com.nineya.spring.proxy.CglibProxyMain.proxyObject(CglibProxyMain.java:53) at com.nineya.spring.proxy.CglibProxyMain.main(CglibProxyMain.java:75) - 
CGLIB性能优于JDK代理。基于上述的代码,删除控制台打印命令,分别对
CGLIB和JDK两种代理方式执行 5 组,每组循环调用一千万次代理方法的任务。for (int i = 0; i < 5; i++) { long start = System.currentTimeMillis(); for (int j = 0; j < 10000000; j++) { proxyInterface(); proxyObject(); } long end = System.currentTimeMillis(); System.out.println("耗时:" + (end - start)); }统计得到的耗时结果如下:
# CGLIB 输出 耗时:7409 耗时:4137 耗时:4211 耗时:4146 耗时:4018 # JDK 输出 耗时:10784 耗时:9181 耗时:9586 耗时:9325 耗时:9111