javascript
面试必会系列 - 1.8 Spring IOC / AOP原理
本文已收錄至 Github(MD-Notes),若博客中圖片模糊或打不開,可以來我的 Github 倉庫,包含了完整圖文:https://github.com/HanquanHq/MD-Notes,涵蓋了互聯網大廠面試必問的知識點,講解透徹,長期更新中,歡迎一起學習探討 ~
更多內容,可以訪問:
面試必會系列專欄:https://blog.csdn.net/sinat_42483341/category_10300357.html
操作系統系列專欄:https://blog.csdn.net/sinat_42483341/category_10519484.html
目錄
- Spring 原理
- 概覽
- IOC
- Spring IOC 常用注解
- 使用注解的方式將 bean 注冊到 IOC 容器中
- @Component
- @Controller
- @Service
- @Repository
- @ComponentScan
- 使用注解的時候,并沒有定義 bean 的 id 和 class,那么 spring 是怎么識別的呢?
- 使用 @Autowired 進行自動注入
- Autowired 是根據什么依據來裝配的呢?by name?by type?
- @AutoWired可以進行定義在方法上
- 自動裝配的注解@AutoWired,@Resource 區別
- IOC 原理
- 為什么有 IOC 容器?它的好處是什么?
- IOC 和 DI 的關系?
- 什么是控制翻轉?
- bean 對象信息讀取
- 創建對象
- 實例化對象
- AOP
- AOP簡介
- AOP 實現機制:動態代理
- 如何實現一個 AOP
Spring 原理
概覽
- IOC
- AOP
IOC
Spring IOC 常用注解
使用注解的方式將 bean 注冊到 IOC 容器中
這四個注解寫在類上面的時候,都可以完成注冊bean 的功能,但是這些規定并不是spring識別的依據
在spring運行過程中,不會對這4個注解做任何區分,看起來都是一樣的,都會完成bean的注冊功能
在實際開發中,最好能分清楚,提高代碼的可讀性
@Component
組件,理論上可以在任何位置添加,在掃描的時候都會完成 bean 的注冊。最偷懶的方式,就是給所有需要注冊的 bean 上面添加 @Component 注解
@Controller
放在控制層,用來接收用戶的請求
@Service
放在業務邏輯層
@Repository
放在 dao 數據訪問層
@ComponentScan
Spring容器在運行的時候,怎么知道從哪個包掃描呢?
所以,在使用上述注解的時候,需要 xml 文件中配置context:conponent-scan,并且導入 context 命名空間
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); PersonController personController = context.getBean("personController", PersonController.class)使用注解的時候,并沒有定義 bean 的 id 和 class,那么 spring 是怎么識別的呢?
是把當前類的名稱首字母小寫來識別的。需要的話,你可以在注解中使用value=修改名稱,一般不會去修改。
使用 @Autowired 進行自動注入
首先,bean 已經被注冊到Spring IOC 容器中了,但是如果不使用 Autowired 的話,沒有被注入到對象中。
@AutoWired 是通過反射的方式注入的。
Autowired 是根據什么依據來裝配的呢?by name?by type?
當使用AutoWired注解的時候,自動裝配的時候是根據類型實現的。
還可以使用@Qualifier注解來指定id的名稱,讓spring不要使用變量名,當使用@Qualifier注解的時候也會有兩種情況:
@AutoWired可以進行定義在方法上
@Controller public class PersonController {/*** 當方法上有@AutoWired注解時:* 1、此方法在bean創建的時候會自動調用* 2、這個方法的每一個參數都會自動注入值* @param personDao*/@Autowiredpublic void test(PersonDao personDao){System.out.println("此方法被調用:"+personDao);}自動裝配的注解@AutoWired,@Resource 區別
在使用自動裝配的時候,出了可以使用@AutoWired注解之外,還可以使用@Resource注解,你需要知道這兩個注解的區別。
@AutoWired:是spring中提供的注解,
@Resource:是jdk中定義的注解,依靠的是java的標準
@AutoWired默認是按照類型進行裝配,默認情況下要求依賴的對象必須存在
@Resource默認是按照名字進行匹配的,同時可以指定name屬性
@AutoWired只適合spring框架,而@Resource擴展性更好
IOC 原理
為什么有 IOC 容器?它的好處是什么?
當我們需要獲取對象的時候,可以創建一個工廠類,讓工廠類幫我們創建對象。能不能把這個過程讓別人來做?
我們只需要知道容器里有對象,我們只要拿來用就好了。至于誰創建的,什么時候創建的,這都不需要你操心。
這時候你會想,假設有一個管理器,給你分配 bean,并且可以滿足你的個性化需求,這樣就好了。于是,我們有了 IOC 容器。
IOC 容器,是使用 Map 存放對象的地方,對象是通過反射創建的。默認情況下,對象在 IOC 容器中都是單例的。如果需要多例,可以修改屬性。
IOC 和 DI 的關系?
IOC 是控制翻轉,DI 是依賴注入。
IOC 和 DI 是從不同的角度描述同一件事情,IOC 是從容器的角度考慮的,而 DI 是從應用程序的角度考慮的。
IOC 只是一種思想,而 DI 才是具體的實現方式。
什么是控制翻轉?
有了 IOC 之后,依賴的對象直接由 IOC 容器創建后,注入到對象中。
由我們主動創建,變成了被動接受,這就是控制反轉。
bean 對象信息讀取
但是,容器怎么知道你需要什么對象呢?你需要告訴容器,比如通過配置 xml 文件,比如使用注解。BeanDefiniton 就是用來定義類的信息的,你把信息傳輸給容器,容器接收到信息之后,才能創建對應的對象。
在程序啟動的時候,需要把這些定義信息讀取進來。但是,有的人用 xml,有的人用注解,怎么統一呢?
這時候,定義一 個 BeanDefinitonReader,用來讀取 Bean 的定義信息,如果以后有了新的方式定義 Bean 信息,只需要實現當前接口,就可以了。BeanDefinitonReader 是一個接口,下面有很多不同的實現類,就是很多不同的讀取方式。
創建對象
拿到對象信息之后,需要進行實例化操作。我們知道,創建對象可以通過 new / 工廠/ 反射 的方式實現。實際上,Spring 是通過反射的方式創建對象的。BeanFactory 工廠,可以用來生產對象、訪問工廠。
// bean 實例化,只是一個空對象,沒有任何屬性值 Constructor constructor = TestClass.class.getConstructor(); Object o = constructor.newInstance();實例化對象
BeanProcessor 里面有 Before / AfterInitialization
AOP
AOP簡介
面向切面編程,AOP是OOP的補充,當我們需要為多個對象引入一個公共行為,比如日志,操作記錄等,就需要在每個對象中引用公共行為,這樣程序就產生了大量的重復代碼,使用AOP可以完美解決這個問題。
AOP 實現機制:動態代理
動態代理和靜態代理的區別是,靜態代理的的代理類是我們自己定義好的,在程序運行之前就已經變異完成,但是動態代理的代理類是在程序運行時創建的。相比于靜態代理,動態代理的優勢在于可以很方便的對代理類的函數進行統一的處理,而不用修改每個代理類中的方法。
- cglib
- jdk
如何實現一個 AOP
AOP:【動態代理】指在程序運行期間動態的將某段代碼切入到指定方法指定位置進行運行的編程方式;1、導入aop模塊;Spring AOP:(spring-aspects)2、定義一個業務邏輯類(MathCalculator);在業務邏輯運行的時候將日志進行打印(方法之前、方法運行結束、方法出現異常,xxx)3、定義一個日志切面類(LogAspects):切面類里面的方法需要動態感知MathCalculator.div運行到哪里然后執行;通知方法:前置通知(@Before):logStart:在目標方法(div)運行之前運行后置通知(@After):logEnd:在目標方法(div)運行結束之后運行(無論方法正常結束還是異常結束)返回通知(@AfterReturning):logReturn:在目標方法(div)正常返回之后運行異常通知(@AfterThrowing):logException:在目標方法(div)出現異常以后運行環繞通知(@Around):動態代理,手動推進目標方法運行(joinPoint.procced())4、給切面類的目標方法標注何時何地運行(通知注解);5、將切面類和業務邏輯類(目標方法所在類)都加入到容器中;6、必須告訴Spring哪個類是切面類(給切面類上加一個注解:@Aspect)7、給配置類中加 @EnableAspectJAutoProxy 【開啟基于注解的aop模式】在Spring中很多的 @EnableXXX;三步:1)、將業務邏輯組件和切面類都加入到容器中;告訴Spring哪個是切面類(@Aspect)2)、在切面類上的每一個通知方法上標注通知注解,告訴Spring何時何地運行(切入點表達式)3)、開啟基于注解的aop模式;@EnableAspectJAutoProxy總結
以上是生活随笔為你收集整理的面试必会系列 - 1.8 Spring IOC / AOP原理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: leetcode 64. 最小路径和(递
- 下一篇: 面试必会系列 - 2.1 MySQL知识