1 JDK动态代理

JDK动态代理依赖于Java反射机制,通过java.lang.reflect.Proxy类和InvocationHandler接口实现。它只能代理实现了接口的类。在运行时,JDK动态代理会生成一个代理类,该代理类实现了目标接口,并将方法调用委托给InvocationHandlerinvoke方法。

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

interface Service {
    void perform();
}

class ServiceImpl implements Service {
    public void perform() {
        System.out.println("Service performed.");
    }
}

class ServiceInvocationHandler implements InvocationHandler {
    private Object target;

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

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

public class JDKProxyDemo {
    public static void main(String[] args) {
        Service service = new ServiceImpl();
        Service proxy = (Service) Proxy.newProxyInstance(
                service.getClass().getClassLoader(),
                service.getClass().getInterfaces(),
                new ServiceInvocationHandler(service)
        );
        proxy.perform();
    }
}

2 cglib动态代理

Cglib(Code Generation Library)基于底层的字节码操作(使用ASM库),通过生成目标类的子类,并在子类中拦截方法调用来实现代理。因此,它可以代理没有接口的普通类。

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

class Service {
    public void perform() {
        System.out.println("Service performed.");
    }
}

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

public class CglibProxyDemo {
    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(Service.class);
        enhancer.setCallback(new ServiceInterceptor());
        Service proxy = (Service) enhancer.create();
        proxy.perform();
    }
}

结论

在实际测试中,JDK动态代理在创建代理实例时的性能优于Cglib,而在方法调用时,Cglib的性能则优于JDK动态代理。这是因为JDK动态代理在方法调用时依赖于反射,而Cglib直接调用生成的子类方法。