Spring两种动态代理的比较

153 阅读2分钟

在Java中,有两种常见的动态代理:JDK动态代理和CGLib动态代理。

  1. JDK动态代理:

    • 原理:JDK动态代理是基于接口的代理,它利用Java的反射机制,在运行时创建一个实现指定接口的代理类。代理类调用方法时会委托给InvocationHandler(调用处理器)来处理具体的逻辑。
    • 区别:JDK动态代理要求目标对象必须实现接口,因为代理类需要实现相同的接口以提供统一的方法调用方式。
    • 示例代码:
interface MyInterface {
            void doSomething();
        }

        class MyRealClass implements MyInterface {
            public void doSomething() {
                System.out.println("Doing something.");
            }
        }

        class MyInvocationHandler implements InvocationHandler {
            private Object target;

            public MyInvocationHandler(Object target) {
                this.target = target;
            }

            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("Before method invocation");
                Object result = method.invoke(target, args);
                System.out.println("After method invocation");
                return result;
            }
        }

        public class Main {
            public static void main(String[] args) {
                MyRealClass realObject = new MyRealClass();
                MyInvocationHandler handler = new MyInvocationHandler(realObject);
                MyInterface proxyObject = (MyInterface) Proxy.newProxyInstance(
                        realObject.getClass().getClassLoader(),
                        realObject.getClass().getInterfaces(),
                        handler
                );
                proxyObject.doSomething();
            }
        }

CGLib动态代理:

  • 原理:CGLib动态代理通过生成目标类的子类来实现代理,不需要目标类实现接口。它使用了字节码生成技术,在运行时动态创建一个目标类的子类,并重写其中的方法实现代理逻辑。
  • 区别:CGLib动态代理不要求目标对象实现接口,可以直接代理普通的类。
  • 示例代码:
class MyRealClass {
    public void doSomething() {
        System.out.println("Doing something.");
    }
}

class MyMethodInterceptor implements MethodInterceptor {
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("Before method invocation");
        Object result = proxy.invokeSuper(obj, args);
        System.out.println("After method invocation");
        return result;
    }
}

public class Main {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(MyRealClass.class);
        enhancer.setCallback(new MyMethodInterceptor());
        MyRealClass proxyObject = (MyRealClass) enhancer.create();
        proxyObject.doSomething();
    }
}

总结:

  • JDK动态代理是基于接口的,需要目标对象实现接口;CGLib动态代理则是基于继承的,可以代理普通类。
  • JDK动态代理利用反射机制创建代理类,而CGLib动态代理通过生成目标类的子类来实现代理。
  • JDK动态代理相对于CGLib动态代理在性能上略有差异,CGLib通常更快,但在某些情况下(如目标类被final修饰)只能使用JDK动态代理。