JDK動態代理和CGLIB動態代理
阿新 • • 發佈:2020-09-12
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) throwsThrowable { // 重寫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("日誌結束" + newDate(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機制實現,通過生成業務類的子類作為代理類。
優點:沒有介面也能實現動態代理,採用位元組碼增強技術,效能也不錯。
缺點:相對底層,難以理解。