Spring AOP實驗之靜態代理
1 AOP的概念和原理
1.1 AOP原理
AOP(Aspect Oriented Programming),也就是面向方面編程的技術。AOP基於IoC基礎,是對OOP的有益補充。
AOP將應用系統分為兩部分,核心業務邏輯(Core business concerns)及橫向的通用邏輯,也就是所謂的方面Crosscutting enterprise concerns,例如,所有大中型應用都要涉及到的持久化管理(Persistent)、事務管理(Transaction Management)、安全管理(Security)、日誌管理(Logging)和調試管理(Debugging)等。
AOP正在成為軟件開發的下一個光環。使用AOP,你可以將處理aspect的代碼註入主程序,通常主程序的主要目的並不在於處理這些aspect。AOP可以防止代碼混亂。
1.2 AOP概念
(1) 方面(Aspect):一個關註點的模塊化,這個關註點實現可能另外橫切多個對象。事務管理是J2EE應用中一個很好的橫切關註點例子。方面用Spring的Advisor或攔截器實現。
(2) 連接點(Joinpoint):程序執行過程中明確的點,如方法的調用或特定的異常被拋出。
(3) 通知(Advice):在特定的連接點,AOP框架執行的動作。各種類型的通知包括“around”、“before”和“throws”通知。通知類型將在下面討論。許多AOP框架包括Spring都是以攔截器做通知模型,維護一個“圍繞”連接點的攔截器鏈。
(4) 切入點(Pointcut):指定一個通知將被引發的一系列連接點的集合。AOP框架必須允許開發者指定切入點,例如,使用正則表達式。
(5) 引入(Introduction):添加方法或字段到被通知的類。Spring允許引入新的接口到任何被通知的對象。例如,你可以使用一個引入使任何對象實現IsModified接口,來簡化緩存。
(6) 目標對象(Target Object):包含連接點的對象,也被稱作被通知或被代理對象。
(7) AOP代理(AOP Proxy):AOP框架創建的對象,包含通知。在Spring中,AOP代理可以是JDK動態代理或CGLIB代理。
(8) 編織(Weaving):組裝方面來創建一個被通知對象。這可以在編譯時完成(例如使用AspectJ編譯器),也可以在運行時完成。Spring和其他純Java AOP框架一樣,在運行時完成織入。
2 AOP之靜態代理
2.1 業務介紹
假設學生為核心類,學生做的事情是代理類。學生需要做的核心業務有:學習(study)、做家庭作業(homeWork);需要做的非核心業務為:準備上課(打開書本、預習)、準備做家庭作業(打開作業本、檢查)。
2.2 創建學生類接口:Student
1 package com.cqvie.proxy.static_; 2 3 public interface Student { 4 5 public void study(String study); 6 public void homeWork(String homework); 7 }
2.3 創建學生實現類:StudentDao,並且實現學生接口(Student)
1 package com.cqvie.proxy.static_; 2 3 public class StudentDao implements Student { 4 5 @Override 6 public void study(String study) { 7 System.err.println("今天的學習內容是:" + study); 8 } 9 10 @Override 11 public void homeWork(String homework) { 12 System.err.println("今天的家庭作業是:" + homework); 13 } 14 15 }
2.4 創建一個學生的代理類:Student_Proxy,並且實現學生接口
1 package com.cqvie.proxy.static_; 2 3 /** 4 * 代理對象(Student_proxy)的目的是幫助核心對象(StudentDao)做非核心的事情。 5 * 但是代理對象(Student_proxy)必須和核心對象(StudentDao)實現共同的接口。 6 */ 7 public class Student_Proxy implements Student { 8 9 //定義一個學生接口 作為屬性,目的是就是在處理完代理需要做的事情之後調用學生需要做的核心業務, 10 //但不是代理具體去做這些核心的事情,只是調用它們而已。 11 private Student stu; 12 13 //創建一個代理的參數為學生接口 的構造函數 14 public Student_Proxy(Student stu) { 15 this.stu = stu; 16 } 17 18 @Override 19 public void study(String study) { 20 21 //這個是代理(Student_proxy)準備學習前需要做的流程: 22 System.out.println("代理:打開書本"); 23 System.out.println("代理:提前預習"); 24 System.out.println("*****************"); 25 26 //通過定義的屬性,並且在調用Student_proxy的含參數的構造函數創建相對應的實例,調用這個具體的實例的方法 27 stu.study(study); 28 29 //這個是代理(G3Student_proxy)準備 後需要做的流程: 30 System.out.println("*****************"); 31 System.out.println("代理:課後復習"); 32 System.out.println("代理:關閉書本"); 33 System.out.println(); 34 } 35 36 @Override 37 public void homeWork(String homework) { 38 39 //這個是代理(Student_proxy)準備做作業前需要做的流程: 40 System.out.println("代理:打開作業本"); 41 System.out.println("代理:準備筆"); 42 System.out.println("*****************"); 43 44 //通過定義的屬性,並且在調用Student_proxy的含參數的構造函數創建相對應的實例,調用這個具體的實例的方法 45 stu.homeWork(homework); 46 47 //這個是代理(G3Student_proxy)準備做作業後需要做的流程: 48 System.out.println("*****************"); 49 System.out.println("代理:檢查作業"); 50 System.out.println("代理:關閉作業本"); 51 System.out.println(); 52 } 53 54 }
2.5 進行測試,定義測試類Test
1 package com.cqvie.proxy.static_; 2 3 public class Test { 4 5 public static void main(String[] args) { 6 7 //創建一個代理對象 8 Student stu = new Student_Proxy(new StudentDao()); 9 //通過這個代理對象執行相關的方法(代理對象和核心對象有共同接口) 10 stu.study("數學"); 11 stu.homeWork("8 * 9 = ?"); 12 } 13 14 }
6. 運行效果如圖所示
Spring AOP實驗之靜態代理