跟我學程式碼架構設計模式之--切面思想和代理模式
最近比較忙,文章只寫要點,具體細節擴充套件請自行蒐集資料。
一 、要解決的問題
java面向物件設計裡面,最初只考慮了類和類繼承這一層縱向關係:越公共越通用的方法都在父類裡面,越具體的方法都在子類裡面。在某一個系統裡面一般會有許許多多的類繼承體系關係,比如人員管理系統中會有人員繼承體系、組織機構繼承體系等等,單看在某一種類的繼承關係裡面各自包含各自體系的操作方法基本沒啥問題,但是有這樣一類操作,比如列印log、事務處理、許可權認證等操作方法,這些方法歸在哪個繼承體系的基類裡面都不合適,但是所有的或者某些組的繼承體系都會需要使用到這些操作,比如有這麼一種需求:需要已有系統的所有類的所有方法呼叫前追加列印log操作方法,單靠繼承這一手段可能就不夠用了,怎麼辦?--- AOP之~
二、拿什麼思想來應對--AOP思想
AOP思想提出了這麼幾種角色:被切入的類,被切入的類中操作方法、需要在被切入的類方法中介入的類、需要介入的類中的操作方法。一句化描述就是我需要用哪個類的哪個方法去切入到哪個類的哪個操作方法中,再具體點還可以指定切入到被切入方法的執行前、執行後、還是異常丟擲後~ 拿打Log舉例:寫一個Log類,log類中包含各個級別的列印日誌操作,操作引數為被打Log的類的類名,這個Log類就是介入類,log方法就是介入操作方法,其他的系統中所有需要列印log的類都是被切入的類,被切入的類中需要列印log的方法為被切入操作方法~
三、具體如何實現--代理模式
要想思想上面的AOP思想,就引入了代理模式或者裝飾模式
1 最直觀的代理--靜態代理
寫法套路:四個角色:1 要代理的類所實現的介面 2 被代理的類 3 代理類 4 介入的類。其中被代理的類和代理的類都實現1中所說的介面;介入的類就是AOP中的介入類來給被代理的類方法提供額外的功能;被代理類作為代理類的成員變數儲存到代理類中。拿打Log舉例,代理類對介面指定的所有方法實現中,先呼叫呼叫Log類中的方法,然後呼叫被代理的類中的對應方法~靜態代理的缺點很明顯,一切都要自己手寫JAVA程式碼然後編譯~ 類多的話 這根本就不好辦~
2 動態代理(JAVAPROXY、ASM、CGLIB、JAVASSIST、BYTEBUDDY都是這一類)
所謂動態代理涉及到的角色和靜態代理其實是一樣的,只不過動態代理是直接操作JAVA編譯出來的位元組碼.class,而不是在JAVA原始碼的層次上做改動,這樣有什麼好處呢:可以執行時期給載入到VM系統中的類動態增強或者直接繼承系統中已有的類來實現執行時的代理類,我們不再需要手動編寫代理類的原始碼然後手動編譯成.class位元組碼了~我們只需要手動寫介入類,這是我們自己的介入業務邏輯類,然後寫動態代理類生成邏輯,把我們的介入類邏輯織入到代理類裡面去就OK了
下面簡要說下常見的動態代理框架~
java自帶的動態代理:只能代理介面~對已有系統的類不好辦~
CGLIB、JAVASSIST、ASM、BYTEBUDDY:可以直接繼承現有類來生成代理類~有的還自帶執行時編譯器
ASM的簡要工作原理:框架先讀取要代理的類,按照固定的方式遍歷位元組碼中的類名、欄位、方法等,對每種型別的遍歷都呼叫使用者指定的責任鏈管道來過濾和修改,管道最終走完後生成修改過的位元組碼,這時候的位元組碼就是動態代理類了,裡面織入了介入類中的方法~
(完)