一、SpringAOP:
⒈AOP:Aspect Oriented Programming 面向切面編程, 實現的是核心業務和非核心業務之間的的分離,讓核心類只做核心業務,代理類只做非核心業務。
⒉目的:
⑴、把核心業務和非核心業務進行分離
⑵、把多個非核心業務處理(點)變成一個切面(之前的非核心業務代碼需要寫多次變成只需要寫一次。)
⒊要求:只有當核心類中有多個業務需要進行處理的時候使用AOP較為合理,如果只有一個業務需要被處理那麼就沒有必要使用AOP了。
二、靜態代理:
1、需要知道核心類(被代理類)是哪一個類,並且有什麼方法。
2、非核心的代碼需要重復寫多次,顯得代碼的結構臃腫,形成代碼冗余。
3、非核心類(代理類)需要實現核心類(被代理類)實現的接口,也就是他們需要實現共同的接口,但是以核心類實現的接口(被代理類)為准。
三、動態代理:
1、不需要知道核心類(被代理類)具體是什麼類。
2、非核心類(代理類)需要實現InvocationHandler接口。
四、靜態代理示例:
1、業務介紹:
假定高三學生為核心類,學生的家人是代理類。高三學生需要做的核心業務有:在家學習(studyAtHome)、在學校學習(studyAtHome);家人需要做的非核心業務為:准備飯菜(買、洗、炒、煮飯)。准備補品(購買、熬制、加佐料)。
2、具體代碼:
⑴、創建一個高三學生的接口:G3Student
package aop_001;
//首先定義一個接口,用來高三學生來是實現, //在這個接口中聲明一個在家學習和一個在學校學習的方法
public interface G3Student { public void studyAtHome(String core); public void studyAtSchool(String core); }
⑵、創建一個高三學生實現類:G3Student_boy,並且這個類實現高三學生接口(G3Student)
package aop_001; //定義一個高三男孩的類(目標對象、核心對象、target對象),實現了高三學生的接口。 public class G3Student_boy implements G3Student { //高三男孩 的第一個業務流程:在家學習 public void studyAtHome(String core) {
//核心的事情在家學習。 System.out.println(core+"在HOME學習"); } //高三男孩 的第二個業務流程:在學校學習 public void studyAtSchool(String core) { //核心的事情在家學習。 System.out.println(core+"在SCHOOOL學習"); } }
⑶、創建一個高三學生的代理類:G3Student_proxy,並且實現了高三學生接口:G3Student。紅色字體需要理解
package aop_001; /* * 代理對象(G3Student_proxy)的目的是幫助核心對象(G3Student_boy / G3Student_girl)做非核心的事情。 * 但是代理對象(G3Student_proxy)必須和核心對象(G3Student_boy / G3Student_girl)實現共同的接口。 */ public class G3Student_proxy implements G3Student { //定義一個高三學生接口 作為屬性,目的是就是在處理完代理需要做的事情之後調用高三男孩或者是高三女孩需要做的核心業務, //但是不是代理具體去做這些核心的事情,只是調用它們而已。 private G3Student G3S; //創建一個代理的參數為 高三學生接口 的構造函數,判斷但傳入的字符串為boy就構造一個高三男孩的實例,如果傳入的參數為girl就構造一個高三女孩的實例。 public G3Student_proxy(String sex) { if("boy".equals(sex)){ G3S = new G3Student_boy(); }else if("girl".equals(sex)){ G3S = new G3Student_girl(); } }
public void studyAtHome(String core){ //這個是代理(G3Student_proxy)准備飯菜的需要做的流程: System.out.println("代理:准備買菜"); System.out.println("代理:准備洗菜"); System.out.println("代理:准備炒菜"); System.out.println("代理:准備煮飯"); System.out.println("-----------------"); //通過定義的屬性,並且在調用G3Student_proxy的含參數的構造函數創建相對應的實例,調用這個具體的實例的方法 G3S.studyAtHome(core);
//這個是代理(G3Student_proxy)准備補品的需要做的流程: System.out.println("-----------------"); System.out.println("代理 :購買補品"); System.out.println("代理 :熬制部品"); System.out.println("代理 :加入佐料"); System.out.println(); } public void studyAtSchool(String core) { //這個是代理准備(G3Student_proxy)飯菜的需要做的流程: System.out.println("代理:准備買菜"); System.out.println("代理:准備洗菜"); System.out.println("代理:准備炒菜"); System.out.println("代理:准備煮飯"); System.out.println("-----------------"); //通過定義的屬性,並且在調用G3Student_proxy的含參數的構造函數創建相對應的實例,調用這個具體的實例的方法 G3S.studyAtSchool(core);
System.out.println("-----------------"); //這個是代理(G3Student_proxy)准備補品的需要做的流程: System.out.println("代理 :購買補品"); System.out.println("代理 :熬制部品"); System.out.println("代理 :加入佐料"); System.out.println(); } }
⑷、進行測試:定義一個測試類 Test
package aop_001; public class Test { public static void main(String[] args) { //創建一個代理對象,並且傳入相對應的參數構造出具體的實例 G3Student b = new G3Student_proxy("boy"); //通過這個代理對象執行相關的方法(代理對象和核心對象有共同接口) b.studyAtHome("小明"); b.studyAtSchool("小明"); } }
測試結果:
3、小結:
由上面的例子我們可以簡單模擬一個靜態代理的實例,但是我們發現,這個代理做的事情會因為核心對象業務多而變得多起來,而且這些代理做的事情都是相同的沒有變化的:
並且,如果我們要修改這些流程中的某一個流程的時候會發現要改多處,而且都是相同的代碼,所以這個時候使用動態代理就可以輕松解決這個問題。
謝謝浏覽 !