1. 程式人生 > >AOP 動態代理 的 原始碼分析

AOP 動態代理 的 原始碼分析

首先 寫一個簡單的 AOP測試檔案:


public void testProxy() {
UserDAO userDAO = new UserDAOImpl();
LogInterceptor li = new LogInterceptor();
li.setTarget(userDAO);
UserDAO userDAOProxy = (UserDAO)Proxy.newProxyInstance(userDAO.getClass().getClassLoader(), userDAO.getClass().getInterfaces(), li);
System.out.println(userDAOProxy.getClass());


userDAOProxy.delete();
userDAOProxy.save(new User());
}


junit測試的時候,發現有些原始碼沒法顯示:到網上 查了一下,發現可能直接展示的 位元組碼。 那什麼情況下 反編譯工具會直接讀取位元組碼呢?

可能原因如下: 反編譯器 對於反編譯的高階語言正確性有所懷疑時,或是某些特殊段不能反編譯成高階語言時,以及需要修改class檔案後重新編譯等等。 


具體原因 和 解釋 參考該文章: http://tieba.baidu.com/p/1703769254


那麼 沒法用debug模式看到 所有原始碼,那麼就 仿寫一個:

這個網址 為我們寫好了:

http://blog.csdn.net/leisore/article/details/6736663


這個動態代理類的 主要特點是 :首先他繼承了 Proxy類,並且實現了 一個介面列表,然後 用 

  1. m3 = Class.forName("cn.leisore.daily._2011_08_31.IBook").getMethod("authors"new Class[0]);  
  2. 得到所有介面的所有方法, 所以代理類 包含的東西包括 所有實際類 實現的介面 和 介面中的方法。

最後 在  AOP 測試檔案中 用  代理類呼叫該 方法時,userDAOProxy.delete(); 會去尋找一個實現介面InvocationHandler的類,在該類中 有一個方法:

public Object invoke(Object proxy, Method m, Object[] args)
throws Throwable { } ,其中的引數表示  proxy表示實際動態生成的代理類, m表示 此次呼叫的方法, args表示 m方法的引數


在invoke() 方法中, 可以加上 beforeMethod() ,afterMethod() 等操作實現 切面程式設計:

public Object invoke(Object proxy, Method m, Object[] args)
throws Throwable {
beforeMethod(m);
m.invoke(target, args);
arterMethod(m);
return null;
}


關於動態代理,記住 proxy,InvocationHandler兩個介面,另外 代理類的具體底層實現 用了 native修飾的方法,不再研究具體怎麼生成的位元組碼。


最後 這篇文章 對整個 流程 有一個很好的解讀,值得一看:

http://rejoy.iteye.com/blog/1627405