Spring框架面試題總結(jié)

1.什么是spring

輕量級(jí)的IOC和AOP容器框架,Spring是一個(gè)開(kāi)源的Java EE開(kāi)發(fā)框架。Spring框架的核心功能可以應(yīng)用在任何Java應(yīng)用程序中,但對(duì)Java EE平臺(tái)上的Web應(yīng)用程序有更好的擴(kuò)展性。Spring框架的目標(biāo)是使得Java EE應(yīng)用程序的開(kāi)發(fā)更加簡(jiǎn)捷,通過(guò)使用POJO為基礎(chǔ)的編程模型促進(jìn)良好的編程風(fēng)格。
spring優(yōu)點(diǎn)
1)spring屬于低侵入式設(shè)計(jì),代碼的污染極低;
2)spring的DI機(jī)制將對(duì)象之間的依賴(lài)關(guān)系交由框架處理,減低組件的耦合性;
3)Spring提供了AOP技術(shù),支持將一些通用任務(wù),如安全、事務(wù)、日志、權(quán)限等進(jìn)行集中式管理,從而提供更好的復(fù)用。
4)spring對(duì)于主流的應(yīng)用框架提供了集成支持。
主要組成模塊
Spring Core:核心類(lèi)庫(kù),提供IOC服務(wù);
Spring Context:提供框架式的Bean訪(fǎng)問(wèn)方式,以及企業(yè)級(jí)功能(JNDI、定時(shí)任務(wù)等);
Spring AOP:AOP服務(wù);
Spring DAO:對(duì)JDBC的抽象,簡(jiǎn)化了數(shù)據(jù)訪(fǎng)問(wèn)異常的處理;
Spring ORM:對(duì)現(xiàn)有的ORM框架的支持;
Spring Web:提供了基本的面向Web的綜合特性,例如多方文件上傳;
Spring MVC:提供面向Web應(yīng)用的Model-View-Controller實(shí)現(xiàn)?!?/p>

2.Spring 事務(wù)實(shí)現(xiàn)方式

編程式事務(wù)管理:通過(guò)編程的方式管理事務(wù),這種方式帶來(lái)了很大的靈活性,但很難維護(hù)。
聲明式事務(wù)管理:將事務(wù)管理和業(yè)務(wù)代碼分離。通過(guò)注解或者XML配置管理事務(wù)。

spring事務(wù)的傳播級(jí)別 @Transactional(propagation=Propagation.REQUIRED)

  • PROPAGATION_REQUIRED 如果當(dāng)前沒(méi)有事務(wù),就新建一個(gè)事務(wù),如果已經(jīng)存在一個(gè)事務(wù)中,加入到這個(gè)事務(wù)中。這是最常見(jiàn)的選擇。
  • PROPAGATION_SUPPORTS 支持當(dāng)前事務(wù),如果當(dāng)前沒(méi)有事務(wù),就以非事務(wù)方式執(zhí)行。
  • PROPAGATION_MANDATORY 使用當(dāng)前的事務(wù),如果當(dāng)前沒(méi)有事務(wù),就拋出異常。
  • PROPAGATION_REQUIRES_NEW 新建事務(wù),如果當(dāng)前存在事務(wù),把當(dāng)前事務(wù)掛起。
  • PROPAGATION_NOT_SUPPORTED 以非事務(wù)方式執(zhí)行操作,如果當(dāng)前存在事務(wù),就把當(dāng)前事務(wù)掛起。
  • PROPAGATION_NEVER 以非事務(wù)方式執(zhí)行,如果當(dāng)前存在事務(wù),則拋出異常。
  • PROPAGATION_NESTED 如果當(dāng)前存在事務(wù),則在嵌套事務(wù)內(nèi)執(zhí)行。如果當(dāng)前沒(méi)有事務(wù),則執(zhí)行與PROPAGATION_REQUIRED類(lèi)似的操作。

3.什么是IOC和DI

IOC控制反轉(zhuǎn):把創(chuàng)建對(duì)象的控制權(quán)利由代碼轉(zhuǎn)移到spring的配置文件中。最直觀的表達(dá)就是,IOC讓對(duì)象的創(chuàng)建不用去new了,可以由spring自動(dòng)生產(chǎn),使用java的反射機(jī)制,根據(jù)配置文件在運(yùn)行時(shí)動(dòng)態(tài)的去創(chuàng)建對(duì)象以及管理對(duì)象,并調(diào)用對(duì)象的方法的。

  • 構(gòu)造器依賴(lài)注入:構(gòu)造器依賴(lài)注入在容器觸發(fā)構(gòu)造器的時(shí)候完成,該構(gòu)造器有一系列的參數(shù),每個(gè)參數(shù)代表注入的對(duì)象。
  • Setter方法依賴(lài)注入:首先容器會(huì)觸發(fā)一個(gè)無(wú)參構(gòu)造函數(shù)或無(wú)參靜態(tài)工廠(chǎng)方法實(shí)例化對(duì)象,之后容器調(diào)用bean中的setter方法完成Setter方法依賴(lài)注入。
    可以同時(shí)使用兩種方式的依賴(lài)注入,最好的選擇是使用構(gòu)造器參數(shù)實(shí)現(xiàn)強(qiáng)制依賴(lài)注入,使用setter方法實(shí)現(xiàn)可選的依賴(lài)關(guān)系。

DI依賴(lài)注入:在程序運(yùn)行期間,由外部容器動(dòng)態(tài)地將依賴(lài)對(duì)象注入到組件中。簡(jiǎn)單定義就是當(dāng)一個(gè)對(duì)象需要另一個(gè)對(duì)象時(shí),可以把另一個(gè)對(duì)象注入到對(duì)象中去。優(yōu)點(diǎn)就是把應(yīng)用的代碼量降到最低,達(dá)到松散耦合度。
BeanFactory 接口提供了一個(gè)先進(jìn)的配置機(jī)制,使得任何類(lèi)型的對(duì)象的配置成為可能。ApplicationContext接口對(duì)BeanFactory(是一個(gè)子接口)進(jìn)行了擴(kuò)展,在BeanFactory的基礎(chǔ)上添加了其他功能,比如與Spring的AOP更容易集成,也提供了處理message resource的機(jī)制(用于國(guó)際化)、事件傳播以及應(yīng)用層的特別配置,比如針對(duì)Web應(yīng)用的WebApplicationContext。org.springframework.beans.factory.BeanFactory 是Spring IoC容器的具體實(shí)現(xiàn),用來(lái)包裝和管理前面提到的各種bean。BeanFactory接口是Spring IoC 容器的核心接口。

4.什么是AOP

aop面向切面編程,允許程序員模塊化橫向業(yè)務(wù)邏輯,或定義核心部分的功能,例如日志管理和事務(wù)管理。Spring AOP使用的動(dòng)態(tài)代理,所謂的動(dòng)態(tài)代理就是說(shuō)AOP框架不會(huì)去修改字節(jié)碼,而是每次運(yùn)行時(shí)在內(nèi)存中臨時(shí)為方法生成一個(gè)AOP對(duì)象,這個(gè)AOP對(duì)象包含了目標(biāo)對(duì)象的全部方法,并且在特定的切點(diǎn)做了增強(qiáng)處理,并回調(diào)原對(duì)象的方法。動(dòng)態(tài)代理可以減少系統(tǒng)中的重復(fù)代碼,降低了模塊間的耦合度,同時(shí)提高了系統(tǒng)的可維護(hù)性??捎糜跈?quán)限認(rèn)證、日志、事務(wù)處理。Spring AOP中的動(dòng)態(tài)代理主要有兩種方式,JDK動(dòng)態(tài)代理和CGLIB動(dòng)態(tài)代理:
JDK代理:基于接口的代理,不支持類(lèi)的代理。核心InvocationHandler接口和Proxy類(lèi),InvocationHandler 通過(guò)invoke()方法反射來(lái)調(diào)用目標(biāo)類(lèi)中的代碼,動(dòng)態(tài)地將橫切邏輯和業(yè)務(wù)編織在一起;接著,Proxy利用 InvocationHandler動(dòng)態(tài)創(chuàng)建一個(gè)符合某一接口的的實(shí)例, 生成目標(biāo)類(lèi)的代理對(duì)象。Proxy.newProxyInstance(ClassLoader,Interfaces,InvocationHandler);

5.Spring框架中都用到了哪些設(shè)計(jì)模式

工廠(chǎng)模式:BeanFactory就是簡(jiǎn)單工廠(chǎng)模式的體現(xiàn),用來(lái)創(chuàng)建對(duì)象的實(shí)例;
單例模式:Bean默認(rèn)為單例模式。
代理模式:Spring的AOP功能用到了JDK的動(dòng)態(tài)代理和CGLIB字節(jié)碼生成技術(shù);
模板方法:用來(lái)解決代碼重復(fù)的問(wèn)題。比如. RestTemplate, JmsTemplate, JpaTemplate。
觀察者模式:定義對(duì)象鍵一種一對(duì)多的依賴(lài)關(guān)系,當(dāng)一個(gè)對(duì)象的狀態(tài)發(fā)生改變時(shí),所有依賴(lài)于它的對(duì)象都會(huì)得到通知被制動(dòng)更新,如Spring中l(wèi)istener的實(shí)現(xiàn)--ApplicationListener。

6.bean的作用域

1)singleton:默認(rèn),每個(gè)容器中只有一個(gè)bean的實(shí)例,單例的模式由BeanFactory自身來(lái)維護(hù),線(xiàn)程不安全
2)prototype:為每一個(gè)bean請(qǐng)求提供一個(gè)實(shí)例,線(xiàn)程安全
3)request:為每一個(gè)網(wǎng)絡(luò)請(qǐng)求創(chuàng)建一個(gè)實(shí)例,在請(qǐng)求完成以后,bean會(huì)失效并被垃圾回收器回收。
4)session:與request范圍類(lèi)似,確保每個(gè)session中有一個(gè)bean的實(shí)例,在session過(guò)期后,bean會(huì)隨之失效。
5)global-session:全局作用域

7.Bean是線(xiàn)程安全的么

Spring框架并沒(méi)有對(duì)單例bean進(jìn)行任何多線(xiàn)程的封裝處理。關(guān)于單例bean的線(xiàn)程安全和并發(fā)問(wèn)題需要開(kāi)發(fā)者自行去搞定。但實(shí)際上,大部分的Spring bean并沒(méi)有可變的狀態(tài)(比如Serview類(lèi)和DAO類(lèi)),所以在某種程度上說(shuō)Spring的單例bean是線(xiàn)程安全的。如果你的bean有多種狀態(tài)的話(huà)(比如 View Model 對(duì)象),就需要自行保證線(xiàn)程安全。最淺顯的解決辦法就是將多態(tài)bean的作用域由“singleton”變更為“prototype”。

8.Spring Bean的生命周期

  • 實(shí)例化 Instantiation
  • 屬性賦值 Populate
  • 初始化 Initialization
  • 銷(xiāo)毀 Destruction
Bean的生命周期.jpg

1.首先容器啟動(dòng)后,會(huì)對(duì)scope為singleton且非懶加載的bean進(jìn)行實(shí)例化(相當(dāng)于程序中的new Xx())
2.Spring將值和Bean的引用注入進(jìn)Bean對(duì)應(yīng)的屬性中
3.如果Bean實(shí)現(xiàn)了BeanNameAware接口,Spring將Bean的ID傳遞給setBeanName()方法(實(shí)現(xiàn)BeanNameAware清主要是為了通過(guò)Bean的引用來(lái)獲得Bean的ID,一般業(yè)務(wù)中是很少有用到Bean的ID的)
4.如果Bean實(shí)現(xiàn)了BeanFactoryAware接口,Spring將調(diào)用setBeanDactory(BeanFactory bf)方法并把BeanFactory容器實(shí)例作為參數(shù)傳入。(實(shí)現(xiàn)BeanFactoryAware 主要目的是為了獲取Spring容器,如Bean通過(guò)Spring容器發(fā)布事件等)
5.如果Bean實(shí)現(xiàn)了ApplicationContextAwaer接口,Spring容器將調(diào)用setApplicationContext(ApplicationContext ctx)方法,把y應(yīng)用上下文作為參數(shù)傳入.(作用與BeanFactory類(lèi)似都是為了獲取Spring容器,不同的是Spring容器在調(diào)用setApplicationContext方法時(shí)會(huì)把它自己作為setApplicationContext 的參數(shù)傳入,而Spring容器在調(diào)用setBeanDactory前需要程序員自己指定(注入)setBeanDactory里的參數(shù)BeanFactory )
6.如果Bean實(shí)現(xiàn)了BeanPostProcess接口,Spring將調(diào)用它們的postProcessBeforeInitialization(預(yù)初始化)方法(作用是在Bean實(shí)例創(chuàng)建成功后對(duì)進(jìn)行增強(qiáng)處理,如對(duì)Bean進(jìn)行修改,增加某個(gè)功能)
7.如果Bean實(shí)現(xiàn)了InitializingBean接口,Spring將調(diào)用它們的afterPropertiesSet方法,作用與在配置文件中對(duì)Bean使用init-method聲明初始化的作用一樣,都是在Bean的全部屬性設(shè)置成功后執(zhí)行的初始化方法。
8.如果Bean實(shí)現(xiàn)了BeanPostProcess接口,Spring將調(diào)用它們的postProcessAfterInitialization(后初始化)方法(作用與6的一樣,只不過(guò)6是在Bean初始化前執(zhí)行的,而這個(gè)是在Bean初始化后執(zhí)行的,時(shí)機(jī)不同 )
9.經(jīng)過(guò)以上的工作后,Bean將一直駐留在應(yīng)用上下文中給應(yīng)用使用,直到應(yīng)用上下文被銷(xiāo)毀10.如果Bean實(shí)現(xiàn)了DispostbleBean接口,Spring將調(diào)用它的destory方法,作用與在配置文件中對(duì)Bean使用destory-method屬性的作用一樣,都是在Bean實(shí)例銷(xiāo)毀前執(zhí)行的方法。

9.BeanFactory和ApplicationContext

ApplicationContext提供了一種解決文檔信息的方法,一種加載文件資源的方式(如圖片),他們可以向監(jiān)聽(tīng)他們的beans發(fā)送消息。另外,容器或者容器中beans的操作,這些必須以bean工廠(chǎng)的編程方式處理的操作可以在應(yīng)用上下文中以聲明的方式處理。應(yīng)用上下文實(shí)現(xiàn)了MessageSource,該接口用于獲取本地消息,實(shí)際的實(shí)現(xiàn)是可選的。

ApplicationContext 應(yīng)用上下文,繼承BeanFactory接口,它是Spring的一各更高級(jí)的容器,提供了更多的有用的功能;

  1. 國(guó)際化(MessageSource)
  2. 訪(fǎng)問(wèn)資源,如URL和文件(ResourceLoader)
  3. 載入多個(gè)(有繼承關(guān)系)上下文 ,使得每一個(gè)上下文都專(zhuān)注于一個(gè)特定的層次,比如應(yīng)用的web層
  4. 消息發(fā)送、響應(yīng)機(jī)制(ApplicationEventPublisher)
  5. AOP(攔截器)

相同點(diǎn):兩者都是通過(guò)xml配置文件加載bean,ApplicationContext和BeanFacotry相比,提供了更多的擴(kuò)展功能。
不同點(diǎn):BeanFactory應(yīng)用啟動(dòng)的時(shí)候占用資源很少;對(duì)資源要求較高的應(yīng)用,比較有優(yōu)勢(shì);
ApplicationContext 所有的Bean在啟動(dòng)的時(shí)候都加載,系統(tǒng)運(yùn)行的速度快; 在啟動(dòng)的時(shí)候所有的Bean都加載了,我們就能在系統(tǒng)啟動(dòng)的時(shí)候,盡早的發(fā)現(xiàn)系統(tǒng)中的配置問(wèn)題;建議web應(yīng)用,在啟動(dòng)的時(shí)候就把所有的Bean都加載了。

10.Spring的自動(dòng)裝配

在spring中,對(duì)象無(wú)需自己查找或創(chuàng)建與其關(guān)聯(lián)的其他對(duì)象,由容器負(fù)責(zé)把需要相互協(xié)作的對(duì)象引用賦予各個(gè)對(duì)象,使用autowire來(lái)配置自動(dòng)裝載模式。
xml配置中共有5種自動(dòng)裝配:
1)no:默認(rèn)的方式是不進(jìn)行自動(dòng)裝配的,通過(guò)手工設(shè)置ref屬性來(lái)進(jìn)行裝配bean。
2)byName:通過(guò)bean的名稱(chēng)進(jìn)行自動(dòng)裝配,如果一個(gè)bean的 property 與另一bean 的name 相同,就進(jìn)行自動(dòng)裝配。
3)byType:通過(guò)參數(shù)的數(shù)據(jù)類(lèi)型進(jìn)行自動(dòng)裝配。
4)constructor:利用構(gòu)造函數(shù)進(jìn)行裝配,并且構(gòu)造函數(shù)的參數(shù)通過(guò)byType進(jìn)行裝配。
5)autodetect:自動(dòng)探測(cè),如果有構(gòu)造方法,通過(guò) construct的方式自動(dòng)裝配,否則使用 byType的方式自動(dòng)裝配。

基于注解的方式:
使用@Autowired注解來(lái)自動(dòng)裝配指定的bean。在使用@Autowired注解之前需要在Spring配置文件進(jìn)行配置,<context:annotation-config />。在啟動(dòng)spring IoC時(shí),容器自動(dòng)裝載了一個(gè)AutowiredAnnotationBeanPostProcessor后置處理器,當(dāng)容器掃描到@Autowied、@Resource或@Inject時(shí),就會(huì)在IoC容器自動(dòng)查找需要的bean,并裝配給該對(duì)象的屬性。

:@Autowired和@Resource之間的區(qū)別
@Autowired 默認(rèn)是按照類(lèi)型裝配注入的,默認(rèn)情況下它要求依賴(lài)對(duì)象必須存在(可以設(shè)置它required屬性為false)。
@Resource 默認(rèn)是按照名稱(chēng)來(lái)裝配注入的,只有當(dāng)找不到與名稱(chēng)匹配的bean才會(huì)按照類(lèi)型來(lái)裝配注入。

@Qualifier 通常和@Autowired一起使用,當(dāng)你想對(duì)注入的過(guò)程做更多的控制,@Qualifier可以幫助你指定做更詳細(xì)配置。一般在兩個(gè)或者多個(gè)bean是相同的類(lèi)型,spring在注入的時(shí)候會(huì)出現(xiàn)混亂。

11.Spring事務(wù)的實(shí)現(xiàn)方式和實(shí)現(xiàn)原理

Spring事務(wù)的本質(zhì)其實(shí)就是數(shù)據(jù)庫(kù)對(duì)事務(wù)的支持,沒(méi)有數(shù)據(jù)庫(kù)的事務(wù)支持,spring是無(wú)法提供事務(wù)功能的。真正的數(shù)據(jù)庫(kù)層的事務(wù)提交和回滾是通過(guò)binlog或者redo log實(shí)現(xiàn)的。

Spring事務(wù)的種類(lèi):編程式事務(wù)管理和聲明式事務(wù)管理兩種方式:
①編程式事務(wù)管理使用TransactionTemplate。
②聲明式事務(wù)管理建立在AOP之上的。其本質(zhì)是通過(guò)AOP功能,對(duì)方法前后進(jìn)行攔截,將事務(wù)處理的功能編織到攔截的方法中,也就是在目標(biāo)方法開(kāi)始之前加入一個(gè)事務(wù),在執(zhí)行完目標(biāo)方法之后根據(jù)執(zhí)行情況提交或者回滾事務(wù)。

聲明式事務(wù)最大的優(yōu)點(diǎn)就是不需要在業(yè)務(wù)邏輯代碼中摻雜事務(wù)管理的代碼,只需在配置文件中做相關(guān)的事務(wù)規(guī)則聲明或通過(guò)@Transactional注解的方式,便可以將事務(wù)規(guī)則應(yīng)用到業(yè)務(wù)邏輯中。聲明式事務(wù)管理要優(yōu)于編程式事務(wù)管理,這正是spring倡導(dǎo)的非侵入式的開(kāi)發(fā)方式,使業(yè)務(wù)代碼不受污染,只要加上注解就可以獲得完全的事務(wù)支持。唯一不足地方是,最細(xì)粒度只能作用到方法級(jí)別,無(wú)法做到像編程式事務(wù)那樣可以作用到代碼塊級(jí)別。

12.Spring框架中有哪些不同類(lèi)型的事件?

1)上下文更新事件(ContextRefreshedEvent):在調(diào)用ConfigurableApplicationContext 接口中的refresh()方法時(shí)被觸發(fā)。
2)上下文開(kāi)始事件(ContextStartedEvent):當(dāng)容器調(diào)用ConfigurableApplicationContext的Start()方法開(kāi)始/重新開(kāi)始容器時(shí)觸發(fā)該事件。
3)上下文停止事件(ContextStoppedEvent):當(dāng)容器調(diào)用ConfigurableApplicationContext的Stop()方法停止容器時(shí)觸發(fā)該事件。
4)上下文關(guān)閉事件(ContextClosedEvent):當(dāng)ApplicationContext被關(guān)閉時(shí)觸發(fā)該事件。容器被關(guān)閉時(shí),其管理的所有單例Bean都被銷(xiāo)毀。
5)請(qǐng)求處理事件(RequestHandledEvent):在Web應(yīng)用中,當(dāng)一個(gè)http請(qǐng)求(request)結(jié)束觸發(fā)該事件。
如果一個(gè)bean實(shí)現(xiàn)了ApplicationListener接口,當(dāng)一個(gè)ApplicationEvent 被發(fā)布以后,bean會(huì)自動(dòng)被通知。

13.Spring常用的注解

@Component 組件,沒(méi)有明確的角色

@Service 在業(yè)務(wù)邏輯層使用

@Repository 在數(shù)據(jù)訪(fǎng)問(wèn)層使用

@Controller 在展現(xiàn)層使用,控制器的聲明

@Autowired 自動(dòng)裝配

@Configuration 聲明當(dāng)前類(lèi)為配置類(lèi),相當(dāng)于xml形式的Spring配置(類(lèi)上)

@Bean 注解在方法上,聲明當(dāng)前方法的返回值為一個(gè)bean,替代xml中的方式

@Configuration 聲明當(dāng)前類(lèi)為配置類(lèi),其中內(nèi)部組合了@Component注解,表明這個(gè)類(lèi)是一個(gè)bean(類(lèi)上)

@ComponentScan 用于對(duì)Component進(jìn)行掃描,相當(dāng)于xml中的(類(lèi)上)

@Value 為屬性注入值(屬性上)

@Profile 通過(guò)設(shè)定Environment的ActiveProfiles來(lái)設(shè)定當(dāng)前context需要使用的配置環(huán)境。(類(lèi)或方法上)

@EnableAspectJAutoProxy 開(kāi)啟對(duì)AspectJ自動(dòng)代理的支持

@EnableAsync 開(kāi)啟異步方法的支持

@EnableScheduling 開(kāi)啟計(jì)劃任務(wù)的支持

14.循環(huán)依賴(lài)

Spring循環(huán)依賴(lài):一個(gè)或多個(gè)對(duì)象實(shí)例之間存在直接或間接的依賴(lài)關(guān)系,這種依賴(lài)關(guān)系構(gòu)成了構(gòu)成一個(gè)環(huán)形調(diào)用。
發(fā)生循環(huán)依賴(lài)的兩個(gè)前提條件是:
1)出現(xiàn)循環(huán)依賴(lài)的Bean必須要是單例(singleton),如果依賴(lài)prototype則完全不會(huì)有此需求。
2)依賴(lài)注入的方式不能全是構(gòu)造器注入的方式,只能解決setter方法的循環(huán)依賴(lài),這是錯(cuò)誤的。

Spring通過(guò)三級(jí)緩存解決了循環(huán)依賴(lài)
一級(jí)緩存 : Map<String,Object> singletonObjects,單例池,用于保存實(shí)例化、注入、初始化完成的bean實(shí)例
二級(jí)緩存 : Map<String,Object> earlySingletonObjects,早期曝光對(duì)象,用于保存實(shí)例化完成的bean實(shí)例
三級(jí)緩存 : Map<String,ObjectFactory<?>> singletonFactories,早期曝光對(duì)象工廠(chǎng),用于保存bean創(chuàng)建工廠(chǎng),以便于后面擴(kuò)展有機(jī)會(huì)創(chuàng)建代理對(duì)象。
當(dāng)A、B兩個(gè)類(lèi)發(fā)生循環(huán)引用時(shí),在A完成實(shí)例化后,就使用實(shí)例化后的對(duì)象去創(chuàng)建一個(gè)對(duì)象工廠(chǎng),并添加到三級(jí)緩存中,如果A被AOP代理,那么通過(guò)這個(gè)工廠(chǎng)獲取到的就是A代理后的對(duì)象,如果A沒(méi)有被AOP代理,那么這個(gè)工廠(chǎng)獲取到的就是A實(shí)例化的對(duì)象。當(dāng)A進(jìn)行屬性注入時(shí),會(huì)去創(chuàng)建B,同時(shí)B又依賴(lài)了A,所以創(chuàng)建B的同時(shí)又會(huì)去調(diào)用getBean(a)來(lái)獲取需要的依賴(lài),此時(shí)的getBean(a)會(huì)從緩存中獲取:

第一步,先獲取到三級(jí)緩存中的工廠(chǎng)。
第二步,調(diào)用對(duì)象工廠(chǎng)的getObject方法來(lái)獲取到對(duì)應(yīng)的對(duì)象,得到這個(gè)對(duì)象后將其注入到B中。緊接著B(niǎo)會(huì)走完它的生命周期流程,包括初始化、后置處理器等。
當(dāng)B創(chuàng)建完后,會(huì)將B再注入到A中,此時(shí)A再完成它的整個(gè)生命周期。至此循環(huán)依賴(lài)結(jié)束

spring進(jìn)行掃描->反射后封裝成beanDefinition對(duì)象->放入beanDefinitionMap->遍歷map->驗(yàn)證(是否單例、是否延遲加載、是否抽象)->推斷構(gòu)造方法->準(zhǔn)備開(kāi)始進(jìn)行實(shí)例->去單例池中查,沒(méi)有->去二級(jí)緩存中找,沒(méi)有提前暴露->生成一個(gè)objectFactory對(duì)象暴露到二級(jí)緩存中->屬性注入,發(fā)現(xiàn)依賴(lài)Y->此時(shí)Y開(kāi)始它的生命周期直到屬性注入,發(fā)現(xiàn)依賴(lài)X->X又走一遍生命周期,當(dāng)走到去二級(jí)緩存中找的時(shí)候找到了->往Y中注入X的objectFactory對(duì)象->完成循環(huán)依賴(lài)。

1)為什么要使用X的objectFacory對(duì)象而不是直接使用X對(duì)象?
利于拓展,程序員可以通過(guò)beanPostProcess接口操作objectFactory對(duì)象生成自己想要的對(duì)象
2)是不是只能支持單例(scope=singleton)而不支持原型(scope=prototype)?
是。因?yàn)閱卫莝pring在啟動(dòng)時(shí)進(jìn)行bean加載放入單例池中,在依賴(lài)的bean開(kāi)始生命周期后,可以直接從二級(jí)緩存中取到它所依賴(lài)的bean的objectFactory對(duì)象從而結(jié)束循環(huán)依賴(lài)。而原型只有在用到時(shí)才會(huì)走生命周期流程,但是原型不存在一個(gè)已經(jīng)實(shí)例化好的bean,所以會(huì)無(wú)限的創(chuàng)建->依賴(lài)->創(chuàng)建->依賴(lài)->...。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容