动态代理主要有两种实现方式:JDK
动态代理和CGLIB
动态代理。
-
JDK动态代理:是基于Java反射机制实现的,只能代理实现了接口的类。方法拦截器实现
InvocationHandler
接口。/** 首先我们定义一个接口Service与它的实现类 */ // 目标接口 interface Service { void performTask(); void anotherTask(); } // 目标类实现接口 class ServiceImpl implements Service { @Override public void performTask() { System.out.println("Executing task in ServiceImpl"); } @Override public void anotherTask() { System.out.println("Executing another task in ServiceImpl"); } }
/** 创建实现InvocationHandler接口的代理类 */ // 动态代理类 class ServiceInvocationHandler implements InvocationHandler { private final Service target; // 目标对象 // 构造函数接受目标对象 public ServiceInvocationHandler(Service target) { this.target = target; } // 代理对象的方法被调用时,invoke 方法会被执行 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 在调用目标方法前添加逻辑 System.out.println("Before executing " + method.getName()); // 通过反射调用目标对象的方法 Object result = method.invoke(target, args); // 在调用目标方法后添加逻辑 System.out.println("After executing " + method.getName()); return result; } }
/** 创建代理对象 */ public class Main { public static void main(String[] args) { // 创建目标对象 Service target = new ServiceImpl(); // 通过 Proxy 类生成代理对象 Service proxyInstance = (Service) Proxy.newProxyInstance( target.getClass().getClassLoader(), // 类加载器 target.getClass().getInterfaces(), // 目标对象实现的接口 new ServiceInvocationHandler(target) // InvocationHandler 的实现 ); // 调用代理对象的方法 proxyInstance.performTask(); proxyInstance.anotherTask(); } }
// 运行结果 Before executing performTask Executing task in ServiceImpl After executing performTask Before executing anotherTask Executing another task in ServiceImpl After executing anotherTask
-
CGLIB动态代理:可以为没有实现接口的类创建代理,通过生成目标代理类的子类来实现代理。方法拦截器实现
MethodInterceptor
接口。// 目标类:需要被代理的类 class Service { public void performTask() { System.out.println("Executing task in Service"); } public void anotherTask() { System.out.println("Executing another task in Service"); } }
// 方法拦截器:通过这个接口可以拦截目标类的方法调用。 class ServiceMethodInterceptor implements MethodInterceptor { @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { // 在方法执行前添加逻辑 System.out.println("Before executing " + method.getName()); // 调用父类(即目标类)的原始方法 Object result = proxy.invokeSuper(obj, args); // 在方法执行后添加逻辑 System.out.println("After executing " + method.getName()); return result; } }
// 动态代理的实现:使用 CGLIB 的 Enhancer 类来创建目标类的代理对象。 import net.sf.cglib.proxy.Enhancer; public class Main { public static void main(String[] args) { // 创建Enhancer对象,类似于代理的构建器 Enhancer enhancer = new Enhancer(); // 设置父类为目标类,即Service类 enhancer.setSuperclass(Service.class); // 设置回调接口,即MethodInterceptor的实现 enhancer.setCallback(new ServiceMethodInterceptor()); // 创建代理对象,这个代理对象是Service类的子类 Service proxy = (Service) enhancer.create(); // 调用代理对象的方法 proxy.performTask(); proxy.anotherTask(); } }
// 运行结果 Before executing performTask Executing task in Service After executing performTask Before executing anotherTask Executing another task in Service After executing anotherTask
总结:
JDK动态代理:一个类没有实现则无法使用JDK动态代理。
CGLIB动态代理:可以为没有实现接口的类创建代理。CGLIB动态代理不可以代理被final修饰的类,这也是他的限制。