JDK 的動態代理:針對實現了接口的類產生代理。
CGlib 的動態代理:針對沒有實現接口的類產生代理,應用的是底層的字節碼增強的技術 生成當前類的子類對象
JDK動態代理實現
1. 創建接口和對應實現類
1 public interface UserService { 2 void login(); 3 void loginOut(); 4 }
1 //實現類 2 public class UserServiceImpl implements UserService { 3 public void login() { 4 System.out.println("login方法觸發"); 5 } 6 public void loginOut() { 7 System.out.println("loginOut方法觸發"); 8 } 9 }
2.創建動態代理類
1 public class PerformHandler implements InvocationHandler { 2 private Object target; //目標對象 3 public PerformHandler(Object target){ 4 this.target = target; 5 } 6 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 7 //本方法中的其他輸出輸入增強 8 System.out.println("方法觸發了"); 9 //執行被代理類 原方法 10 Object invoke = method.invoke(target, args); 11 System.out.println("執行完畢了"); 12 return invoke; 13 } 14 }
測試
1 @Test 2 public void test1(){ 3 //測試JDK動態代理技術 4 UserService userService = new UserServiceImpl(); 5 PerformHandler performHandler = new PerformHandler(userService); 6 userService = (UserService) 7 Proxy.newProxyInstance(userService.getClass().getClassLoader(), 8 userService.getClass().getInterfaces(), 9 performHandler 10 ); 11 userService.login(); 12 }
測試結果: 在調用接口方法的前后都會添加代理類的方法!
CGlib實現代理
使用JDK創建代理有一個限制,它只能為接口創建代理實例.這一點可以從Proxy的接口方法
newProxyInstance(ClassLoader loader,Class [] interfaces,InvocarionHandler h)中看的很清楚
第二個入參 interfaces就是需要代理實例實現的接口列表.
對於沒有通過接口定義業務方法的類,如何動態創建代理實例呢? JDK動態代理技術顯然已經黔驢技窮,CGLib
作為一個替代者,填補了這一空缺.
GCLib采用底層的字節碼技術,可以為一個類創建子類,在子類中采用方法攔截的技術攔截所有父類方法的調用
並順勢織入橫切邏輯.
1. 創建創建CGLib代理器
1 public class CglibProxy implements MethodInterceptor { 2 3 private Enhancer enhancer = new Enhancer(); 4 //設置被代理對象 5 public Object getProxy(Class clazz){ 6 enhancer.setSuperclass(clazz); 7 enhancer.setCallback(this); 8 return enhancer.create(); 9 } 10 @Override 11 public Object intercept(Object obj, Method method, 12 Object[] objects, 13 MethodProxy methodProxy) throws Throwable { 14 System.out.println("CGLig代理之前之前"); 15 Object invoke = methodProxy.invokeSuper(obj,objects); 16 System.out.println("CGLig代理之前之后"); 17 return invoke; 18 } 19 20 }
測試
1 @Test 2 public void test2(){ 3 //TODO CGlib實現 4 CglibProxy cglibProxy = new CglibProxy(); 5 UserServiceImpl userService= (UserServiceImpl) 6 cglibProxy.getProxy(UserServiceImpl.class); 7 userService.login(); 8 }
結果: