Spring的 AOP底層用到兩種代理機制


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 }

結果:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM