1. 程式人生 > 實用技巧 >JDK動態代理和CGLIB動態代理

JDK動態代理和CGLIB動態代理

JDK動態代理實現

被代理類(需實現介面)

 1 public class UserServiceImp implements UserService{
 2     @Override
 3     public void doService() {
 4         System.out.println(this.getClass() + "doService");
 5         try {
 6             Thread.sleep(2000);
 7         } catch (InterruptedException e) {
 8             e.printStackTrace();
9 } 10 } 11 }

擴充套件類

 1 public class LogHandler implements InvocationHandler {
 2 
 3     Object target;
 4 
 5     public LogHandler(Object target) {
 6         this.target = target;
 7     }
 8 
 9     @Override
10     public Object invoke(Object proxy, Method method, Object[] args) throws
Throwable { // 重寫invoke方法 11 before(); 12 method.invoke(target, args); 13 after(); 14 return null; 15 } 16 public void before() { 17 System.out.println("日誌開始" + new Date(System.currentTimeMillis())); 18 } 19 public void after() { 20 System.out.println("日誌結束" + new
Date(System.currentTimeMillis())); 21 } 22 }

測試

 1 public class Test {
 2     public static void main(String[] args) {
 3         System.getProperties().setProperty("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
 4         UserServiceImp userService = new UserServiceImp(); // 建立被代理類物件
 5         LogHandler logHandler = new LogHandler(userService); // 建立擴充套件類物件,傳入被代理類物件
 6         ClassLoader classLoader = userService.getClass().getClassLoader(); // 獲取類載入器
 7         Class[] interfaces = userService.getClass().getInterfaces(); // 獲取所有介面
 8         UserService proxy = (UserService) Proxy.newProxyInstance(classLoader, interfaces, logHandler); // 建立代理物件
 9         proxy.doService();
10     }
11 }

CGLIB動態代理實現

被代理類

 1 public class MyService {
 2 
 3     public void doService() {
 4         System.out.println(this.getClass() + "doService");
 5         try {
 6             Thread.sleep(2000);
 7         } catch (InterruptedException e) {
 8             e.printStackTrace();
 9         }
10     }
11 }

擴充套件類

 1 public class LogHandler implements MethodInterceptor {
 2     @Override
 3     public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
 4         before();
 5         methodProxy.invokeSuper(o, objects);
 6         after();
 7         return null;
 8     }
 9     public void before() {
10         System.out.println("日誌開始" + new Date(System.currentTimeMillis()));
11     }
12     public void after() {
13         System.out.println("日誌結束" + new Date(System.currentTimeMillis()));
14     }
15 }

測試

1 public class Test {
2     public static void main(String[] args) {
3         Enhancer enhancer = new Enhancer();
4         enhancer.setSuperclass(MyService.class);
5         enhancer.setCallback(new LogHandler());
6         MyService myService = (MyService)enhancer.create();
7         myService.doService();
8     }
9 }

JDK動態代理與CGLIB動態代理對比

JDK動態代理

基於Java反射機制實現,必須要實現了介面的業務類才能用這種方法生成代理。

優點:解決了靜態代理中冗餘的代理實現類問題。

缺點:代理類本身已經繼承了Proxy,所以基於介面設計實現,如果業沒有介面,會丟擲異常。

CGLIB動態代理

基於ASM機制實現,通過生成業務類的子類作為代理類。

優點:沒有介面也能實現動態代理,採用位元組碼增強技術,效能也不錯。

缺點:相對底層,難以理解。