目錄
- 1 AOP工作流程
- 2 AOP核心概念
歡迎大家回到《 Java教程之Spring30天快速入門》,本教程所有示例均基于Maven實現,如果您對Maven還很陌生,請移步本人的博文《 如何在windows11下安裝Maven并配置以及 IDEA配置Maven環境》,本文的上一篇為《 AOP入門案例實戰詳解》
AOP的入門案例已經完成,對于剛才案例的執行過程,我們就得來分析分析,這一節我們主要講解兩個知識點: AOP工作流程和AOP核心概念。其中核心概念是對前面核心概念的補充。
1 AOP工作流程
由于AOP是基于Spring容器管理的bean做的增強,所以整個工作過程需要從Spring加載bean說起:
流程1:Spring容器啟動
- 容器啟動就需要去加載bean,哪些類需要被加載呢?
- 需要被增強的類,如:BookServiceImpl
- 通知類,如:MyAdvice
- 注意此時bean對象還沒有創建成功
流程2:讀取所有切面配置中的切入點
- 上面這個例子中有兩個切入點的配置,但是第一個ptx()并沒有被使用,所以不會被讀取。
流程3:初始化bean
判定bean對應的類中的方法是否匹配到任意切入點
- 注意第1步在容器啟動的時候,bean對象還沒有被創建成功。
- 要被實例化bean對象的類中的方法和切入點進行匹配
- 匹配失敗,創建原始對象,如UserDao
- 匹配失敗說明不需要增強,直接調用原始對象的方法即可。
- 匹配成功,創建原始對象(目標對象)的代理對象,如: BookDao
- 匹配成功說明需要對其進行增強
- 對哪個類做增強,這個類對應的對象就叫做目標對象
- 因為要對目標對象進行功能增強,而采用的技術是動態代理,所以會為其創建一個代理對象
- 最終運行的是代理對象的方法,在該方法中會對原始方法進行功能增強
- 匹配失敗,創建原始對象,如UserDao
流程4:獲取bean執行方法
- 獲取的bean是原始對象時,調用方法并執行,完成操作
- 獲取的bean是代理對象時,根據代理對象的運行模式運行原始方法與增強的內容,完成操作驗證容器中是否為代理對象
為了驗證IOC容器中創建的對象和我們剛才所說的結論是否一致,首先先把結論理出來:
- 如果目標對象中的方法會被增強,那么容器中將存入的是目標對象的代理對象
- 如果目標對象中的方法不被增強,那么容器中將存入的是目標對象本身。
驗證思路
1.要執行的方法,不被定義的切入點包含,即不要增強,打印當前類的getClass()方法
2.要執行的方法,被定義的切入點包含,即要增強,打印出當前類的getClass()方法
3.觀察兩次打印的結果
步驟1:修改App類,獲取類的類型
public class App {public static void main(String[] args) {ApplicationContext ctx = newAnnotationConfigApplicationContext(SpringConfig.class);BookDao bookDao = ctx.getBean(BookDao.class);System.out.println(bookDao);System.out.println(bookDao.getClass());}
}
步驟2:修改MyAdvice類,不增強
因為定義的切入點中,被修改成update1 ,所以BookDao中的update方法在執行的時候,就不會被增
強,所以容器中的對象應該是目標對象本身。
@Component
@Aspect
public class MyAdvice {@Pointcut("execution(void com.itheima.dao.BookDao.update1())")private void pt(){}@Before("pt()")public void method(){System.out.println(System.currentTimeMillis());}
}
步驟3:運行程序
步驟4:修改MyAdvice類,增強
因為定義的切入點中,被修改成update ,所以BookDao中的update方法在執行的時候,就會被增
強,所以容器中的對象應該是目標對象的代理對象
@Component
@Aspect
public class MyAdvice {@Pointcut("execution(void com.itheima.dao.BookDao.update())")private void pt(){}@Before("pt()")public void method(){System.out.println(System.currentTimeMillis());}
}
步驟5:運行程序
至此對于剛才的結論,我們就得到了驗證,這塊大家需要注意的是:
不能直接打印對象,從上面兩次結果中可以看出,直接打印對象走的是對象的toString方法,不管是不是代理對象打印的結果都是一樣的,原因是內部對toString方法進行了重寫。
2 AOP核心概念
在上面介紹AOP的工作流程中,我們提到了兩個核心概念,分別是:
- 目標對象(Target):原始功能去掉共性功能對應的類產生的對象,這種對象是無法直接完成最終工作的
- 代理(Proxy):目標對象無法直接完成工作,需要對其進行功能回填,通過原始對象的代理對象實現
上面這兩個概念比較抽象,簡單來說,
目標對象就是要增強的類[如:BookServiceImpl類]對應的對象,也叫原始對象,不能說它不能運
行,只能說它在運行的過程中對于要增強的內容是缺失的。
SpringAOP是在不改變原有設計(代碼)的前提下對其進行增強的,它的底層采用的是代理模式實現
的,所以要對原始對象進行增強,就需要對原始對象創建代理對象,在代理對象中的方法把通知
[如:MyAdvice中的method方法]內容加進去,就實現了增強,這就是我們所說的代理(Proxy)。
小結
通過這一節中,我們需要掌握的內容有:
- 能說出AOP的工作流程
- AOP的核心概念
- 目標對象、連接點、切入點
- 通知類、通知
- 切面
- 代理
- SpringAOP的本質或者可以說底層實現是通過代理模式。