Java 動態代理實現
- 一、JDK動態代理
- 二、CGLIB動態代理
- 三、動態代理的應用場景
- 四、JDK代理與CGLIB代理比較
動態代理是Java中一種強大的技術,它允許在運行時創建代理對象,用于攔截對目標對象的方法調用。
一、JDK動態代理
JDK動態代理是Java標準庫提供的代理實現,基于接口。
- 定義接口
interface UserService {void addUser(String name);
}
- 實現接口
class UserServiceImpl implements UserService {@Overridepublic void addUser(String name) {System.out.println("添加用戶" + name);}
}
- 實現InvocationHandler
class UserServiceInvocationHandler implements InvocationHandler {private Object target;public UserServiceInvocationHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("--- 前置處理 ---");Object result = method.invoke(target, args);System.out.println("--- 后置處理 ---");return result;}
}
- 創建代理
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;public class JdkProxyDemo {public static void main(String[] args) {UserService userService = new UserServiceImpl();UserServiceInvocationHandler invocationHandler = new UserServiceInvocationHandler(userService);UserService proxy = (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(),userService.getClass().getInterfaces(), invocationHandler);proxy.addUser("張三");}
}
二、CGLIB動態代理
當目標類沒有實現接口時,可以使用CGLIB庫實現動態代理。
- 添加CGLIB依賴(Maven)
<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.3.0</version>
</dependency>
- 目標類(不需要實現接口)
class ProductService {public void addProduct(String name) {System.out.println("添加產品: " + name);}
}
- 方法攔截器
class ProductMethodInterceptor implements MethodInterceptor {@Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {System.out.println("--- 前置處理 ---");// 調用父類方法Object result = proxy.invokeSuper(obj, args);System.out.println("--- 后置處理 ---");return result;}
}
- 創建代理
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;public class CglibProxyDemo {public static void main(String[] args) {ProductMethodInterceptor interceptor = new ProductMethodInterceptor();Enhancer enhancer = new Enhancer();enhancer.setSuperclass(ProductService.class);enhancer.setCallback(interceptor);ProductService proxy = (ProductService) enhancer.create();proxy.addProduct("手機");}
}
三、動態代理的應用場景
- AOP編程:如Spring的AOP功能
- 遠程方法調用:如RPC框架
- 事務管理
- 日志記錄
- 權限控制
- 性能監控
四、JDK代理與CGLIB代理比較
特性 | JDK動態代理 | CGLIB動態代理 |
---|---|---|
基于 | 接口 | 類 |
性能 | 創建快,運行慢 | 創建慢,運行快 |
限制 | 只能代理接口 | 不能代理final類和方法 |
依賴 | Java內置 | 需要第三方庫 |
實現原理 | 反射 | 字節碼生成 |
在Spring框架中,如果目標對象實現了接口,默認使用JDK動態代理,否則使用CGLIB代理。