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類,並且實現了 一個介面列表,然後 用
- m3 = Class.forName("cn.leisore.daily._2011_08_31.IBook").getMethod("authors", new Class[0]);
- 得到所有介面的所有方法, 所以代理類 包含的東西包括 所有實際類 實現的介面 和 介面中的方法。
最後 在 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