新聞中心
一、學(xué)習(xí)指引
Spring創(chuàng)建Bean時(shí)如何指定Bean的依賴(lài)順序呢?

創(chuàng)新互聯(lián)建站專(zhuān)業(yè)為企業(yè)提供大渡口網(wǎng)站建設(shè)、大渡口做網(wǎng)站、大渡口網(wǎng)站設(shè)計(jì)、大渡口網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁(yè)設(shè)計(jì)與制作、大渡口企業(yè)網(wǎng)站模板建站服務(wù),十年大渡口做網(wǎng)站經(jīng)驗(yàn),不只是建網(wǎng)站,更提供有價(jià)值的思路和整體網(wǎng)絡(luò)服務(wù)。
在實(shí)際開(kāi)發(fā)項(xiàng)目的過(guò)程中,經(jīng)常會(huì)遇到這樣一種場(chǎng)景:在開(kāi)發(fā)一個(gè)A功能模塊時(shí),這個(gè)A功能模塊可能會(huì)依賴(lài)另一個(gè)B功能模塊。此時(shí),就需要先開(kāi)發(fā)B功能模塊,然后在開(kāi)發(fā)A功能模塊,在A功能模塊中調(diào)用B功能模塊的功能。
在Spring中創(chuàng)建Bean對(duì)象也是如此,可以通過(guò)某種方式指定Spring中創(chuàng)建Bean的依賴(lài)順序,Spring會(huì)根據(jù)創(chuàng)建Bean的依賴(lài)順序來(lái)創(chuàng)建對(duì)應(yīng)的Bean對(duì)象。這個(gè)指定創(chuàng)建Bean依賴(lài)順序的注解就是@DependsOn注解。
本章,就一起深入探討下Spring的@DependsOn注解。
二、注解說(shuō)明
關(guān)于@DependsOn注解的一點(diǎn)點(diǎn)說(shuō)明~~
@DependsOn注解是Spring中提供的一個(gè)指定Spring創(chuàng)建Bean的依賴(lài)順序的注解。例如,在Spring中需要?jiǎng)?chuàng)建A對(duì)象和B對(duì)象,可以使用@DependsOn注解指定創(chuàng)建A對(duì)象時(shí)依賴(lài)B對(duì)象,此時(shí),在Spring中就會(huì)先創(chuàng)建B對(duì)象,然后再創(chuàng)建A對(duì)象。
2.1 注解源碼
@DependsOn注解可以標(biāo)注到類(lèi)或方法上,可以控制bean的創(chuàng)建、初始化和銷(xiāo)毀方法的執(zhí)行順序。源碼詳見(jiàn):org.springframework.context.annotation.DependsOn。
/**
* @author Juergen Hoeller
* @since 3.0
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface DependsOn {
String[] value() default {};
}
從@DependsOn注解的源碼可以看出,@DependsOn注解是從Spring 3.0版本開(kāi)始提供的注解。其中,只提供了一個(gè)String數(shù)組類(lèi)型的value屬性,含義如下所示。
- value:表示指定的Bean的唯一標(biāo)識(shí),被指定的Bean會(huì)在Spring創(chuàng)建當(dāng)前Bean之前被創(chuàng)建。
2.2 注解使用場(chǎng)景
@DependsOn注解主要用于指定當(dāng)前Bean對(duì)象所依賴(lài)的其他Bean對(duì)象。Spring在創(chuàng)建當(dāng)前Bean之前,會(huì)先創(chuàng)建由@DependsOn注解指定的依賴(lài)Bean,在Spring中使用@DependsOn注解的場(chǎng)景通常會(huì)有以下幾種場(chǎng)景:
(1)在某些情況下,Bean不是通過(guò)屬性或構(gòu)造函數(shù)參數(shù)顯式依賴(lài)于另一個(gè)Bean的,但是卻需要在創(chuàng)建一個(gè)Bean對(duì)象之前,需要先創(chuàng)建另一個(gè)Bean對(duì)象,此時(shí)就可以使用@DependsOn注解。
(2)在單例Bean的情況下@DependsOn既可以指定初始化依賴(lài)順序,也可以指定Bean相應(yīng)的銷(xiāo)毀執(zhí)行順序。
(3)@DependsOn注解可標(biāo)注到任何直接或間接帶有@Component注解的Bean或標(biāo)注到@Bean注解的方法上,可以控制Bean的創(chuàng)建、初始化和銷(xiāo)毀方法執(zhí)行順序。
(4)觀察者模式可以分為事件,事件源和監(jiān)聽(tīng)器三個(gè)組件,如果在Spring中需要實(shí)現(xiàn)觀察者模式時(shí),就可以使用@DependsOn注解實(shí)現(xiàn)監(jiān)聽(tīng)器的Bean對(duì)象在事件源的Bean對(duì)象之前被創(chuàng)建。
三、使用案例
@DependsOn注解案例實(shí)戰(zhàn)~~
Spring的@DependsOn注解可以標(biāo)注到類(lèi)或方法上,所以,本節(jié),會(huì)列舉@DependsOn注解標(biāo)注到類(lèi)和方法上兩個(gè)案例。
3.1 標(biāo)注到類(lèi)上的案例
本節(jié),主要使用@DependsOn注解標(biāo)注到類(lèi)上來(lái)實(shí)現(xiàn)Spring創(chuàng)建Bean的依賴(lài)順序案例,具體實(shí)現(xiàn)步驟如下所示。
(1)新建DependsOnClassA類(lèi)
DependsOnClassA類(lèi)的源碼詳見(jiàn):spring-annotation-chapter-07工程下的io.binghe.spring.annotation.chapter07.bean.DependsOnClassA。
@Component(value = "dependsOnClassA")
@DependsOn(value = {"dependsOnClassB"})
public class DependsOnClassA {
private final Logger logger = LoggerFactory.getLogger(DependsOnClassA.class);
public DependsOnClassA(){
logger.info("執(zhí)行DependsOnClassA的構(gòu)造方法");
}
}
可以看到,DependsOnClassA類(lèi)上使用@Component注解標(biāo)注,并且指定了Bean的名稱(chēng)為dependsOnClassA,以及使用@DependsOn注解指定了依賴(lài)的Bean名稱(chēng)為dependsOnClassB。
(2)新建DependsOnClassB類(lèi)
DependsOnClassB類(lèi)的源碼詳見(jiàn):spring-annotation-chapter-07工程下的io.binghe.spring.annotation.chapter07.bean.DependsOnClassB。
@Component(value = "dependsOnClassB")
public class DependsOnClassB {
private final Logger logger = LoggerFactory.getLogger(DependsOnClassB.class);
public DependsOnClassB(){
logger.info("執(zhí)行DependsOnClassB的構(gòu)造方法");
}
}
可以看到,在DependsOnClassB類(lèi)上標(biāo)注了@Component注解,指定了Bean對(duì)象的名稱(chēng)為dependsOnClassB。
由DependsOnClassA類(lèi)和DependsOnClassB類(lèi)可以看出,在Spring中創(chuàng)建DependsOnClassA類(lèi)的對(duì)象時(shí),會(huì)依賴(lài)DependsOnClassB類(lèi)的對(duì)象。所以,在Spring中,創(chuàng)建DependsOnClassA類(lèi)的對(duì)象之前,會(huì)先創(chuàng)建DependsOnClassB類(lèi)的對(duì)象。
(3)新建DependsOnConfig類(lèi)
DependsOnConfig類(lèi)的源碼詳見(jiàn):spring-annotation-chapter-07工程下的io.binghe.spring.annotation.chapter07.config.DependsOnConfig。
@Configuration
@ComponentScan(basePackages = "io.binghe.spring.annotation.chapter07")
public class DependsOnConfig {
}
可以看到,DependsOnConfig類(lèi)的實(shí)現(xiàn)比較簡(jiǎn)單,在DependsOnConfig類(lèi)上標(biāo)注了@Configuration注解,表示這是一個(gè)Spring的配置類(lèi),并且使用@ComponentScan注解指定了掃描的基礎(chǔ)包名。
(4)新建DependsOnTest類(lèi)
DependsOnTest類(lèi)的源碼詳見(jiàn):spring-annotation-chapter-07工程下的io.binghe.spring.annotation.chapter07.DependsOnTest。
public class DependsOnTest {
public static void main(String[] args) {
new AnnotationConfigApplicationContext(DependsOnConfig.class);
}
}
可以看到,DependsOnTest類(lèi)作為測(cè)試案例的啟動(dòng)類(lèi),整體實(shí)現(xiàn)比較簡(jiǎn)單,就是在main()方法中創(chuàng)建Spring的IOC容器。
(5)測(cè)試DependsOnTest類(lèi)
運(yùn)行DependsOnTest類(lèi)中的main()方法,輸出的結(jié)果信息如下所示。
14:56:17.977 [main] INFO DependsOnClassB - 執(zhí)行DependsOnClassB的構(gòu)造方法
14:56:17.978 [main] INFO DependsOnClassA - 執(zhí)行DependsOnClassA的構(gòu)造方法
可以看到,當(dāng)@DependsOn注解標(biāo)注到類(lèi)上時(shí),Spring在創(chuàng)建標(biāo)注了@DependsOn注解的類(lèi)的Bean對(duì)象之前,會(huì)先創(chuàng)建使用@DependsOn注解指定的Bean對(duì)象。
3.2 標(biāo)注到方法上的案例
本節(jié),主要使用@DependsOn注解標(biāo)注到方法上來(lái)實(shí)現(xiàn)Spring創(chuàng)建Bean的依賴(lài)順序案例,并且本節(jié)的案例程序是在3.1節(jié)的基礎(chǔ)上擴(kuò)展,具體實(shí)現(xiàn)步驟如下所示。
(1)新建DependsOnMethodA類(lèi)
DependsOnMethodA類(lèi)的源碼詳見(jiàn):spring-annotation-chapter-07工程下的io.binghe.spring.annotation.chapter07.bean.DependsOnMethodA。
public class DependsOnMethodA {
private final Logger logger = LoggerFactory.getLogger(DependsOnMethodA.class);
public DependsOnMethodA(){
logger.info("執(zhí)行DependsOnMethodA的構(gòu)造方法");
}
}
可以看到,DependsOnMethodA類(lèi)就是一個(gè)簡(jiǎn)單的實(shí)體類(lèi),這里不再贅述。
(2)新增DependsOnMethodB類(lèi)
DependsOnMethodB類(lèi)的源碼詳見(jiàn):spring-annotation-chapter-07工程下的io.binghe.spring.annotation.chapter07.bean.DependsOnMethodB。
public class DependsOnMethodB {
private final Logger logger = LoggerFactory.getLogger(DependsOnMethodB.class);
public DependsOnMethodB(){
logger.info("執(zhí)行DependsOnMethodB的構(gòu)造方法");
}
}
可以看到,DependsOnMethodB類(lèi)就是一個(gè)簡(jiǎn)單的實(shí)體類(lèi),這里不再贅述。
(3)修改DependsOnConfig類(lèi)
在DependsOnConfig類(lèi)中使用@Bean注解分別創(chuàng)建DependsOnMethodA類(lèi)和DependsOnMethodB類(lèi)的Bean對(duì)象,如下所示。
@DependsOn(value = {"dependsOnMethodB"})
@Bean(value = "dependsOnMethodA")
public DependsOnMethodA dependsOnMethodA(){
return new DependsOnMethodA();
}
@Bean(value = "dependsOnMethodB")
public DependsOnMethodB dependsOnMethodB(){
return new DependsOnMethodB();
}
可以看到,在DependsOnConfig類(lèi)中使用@Bean注解創(chuàng)建DependsOnMethodA類(lèi)的Bean對(duì)象時(shí),使用@DependsOn注解依賴(lài)了名稱(chēng)為dependsOnMethodB的Bean對(duì)象。
(4)測(cè)試DependsOnTest類(lèi)
運(yùn)行DependsOnTest類(lèi)中的main()方法,輸出的結(jié)果信息如下所示。
15:16:24.523 [main] INFO DependsOnClassB - 執(zhí)行DependsOnClassB的構(gòu)造方法
15:16:24.524 [main] INFO DependsOnClassA - 執(zhí)行DependsOnClassA的構(gòu)造方法
15:16:24.528 [main] INFO DependsOnMethodB - 執(zhí)行DependsOnMethodB的構(gòu)造方法
15:16:24.529 [main] INFO DependsOnMethodA - 執(zhí)行DependsOnMethodA的構(gòu)造方法
可以看到,當(dāng)@DependsOn注解標(biāo)注到方法上時(shí),Spring在執(zhí)行標(biāo)注了@DependsOn注解的方法創(chuàng)建Bean對(duì)象前,先執(zhí)行其他方法來(lái)創(chuàng)建使用@DependsOn注解指定的Bean對(duì)象。
通過(guò)上述兩個(gè)案例得知:@DependsOn注解可以指定Spring中Bean對(duì)象創(chuàng)建的依賴(lài)順序,并且Spring在創(chuàng)建當(dāng)前Bean之前,會(huì)先創(chuàng)建由@DependsOn注解指定的依賴(lài)Bean
四、源碼時(shí)序圖
結(jié)合時(shí)序圖理解源碼會(huì)事半功倍,你覺(jué)得呢?
本節(jié),就以源碼時(shí)序圖的方式,直觀的感受下@DependsOn注解在Spring源碼層面的執(zhí)行流程。本節(jié),主要從注冊(cè)Bean、調(diào)用Bean工廠后置處理器和創(chuàng)建Bean三個(gè)方面分析源碼時(shí)序圖。
4.1 注冊(cè)Bean的源碼時(shí)序圖
@DependsOn注解涉及到的注冊(cè)Bean的源碼時(shí)序圖如圖7-1所示。
由圖7-1可以看出,@DependsOn注解在注冊(cè)Bean的流程中涉及到DependsOnTest類(lèi)、AnnotationConfigApplicationContext類(lèi)、AnnotatedBeanDefinitionReader類(lèi)、AnnotationConfigUtils類(lèi)、BeanDefinitionReaderUtils類(lèi)和DefaultListableBeanFactory類(lèi)。具體的源碼執(zhí)行細(xì)節(jié)參見(jiàn)源碼解析部分。
4.2 調(diào)用Bean工廠后置處理器的源碼時(shí)序圖
@DependsOn注解涉及到的調(diào)用Bean工廠后置處理器的源碼時(shí)序圖如圖7-2~7-4所示。
由圖7-2~7-4可以看出,@DependsOn注解涉及到的調(diào)用Bean工廠后置處理器的流程涉及到DependsOnTest類(lèi)、AnnotationConfigApplicationContext類(lèi)、AbstractApplicationContext類(lèi)、PostProcessorRegistrationDelegate類(lèi)、ConfigurationClassPostProcessor類(lèi)、ConfigurationClassParser類(lèi)、ComponentScanAnnotationParser類(lèi)、ClassPathBeanDefinitionScanner類(lèi)、AnnotationConfigUtils類(lèi)、BeanDefinitionReaderUtils類(lèi)和DefaultListableBeanFactory類(lèi)。具體的源碼執(zhí)行細(xì)節(jié)參見(jiàn)源碼解析部分。
4.3 創(chuàng)建Bean的源碼時(shí)序圖
@DependsOn注解涉及到的創(chuàng)建Bean的源碼時(shí)序圖如圖7-5所示。
由圖7-5可以看出,@DependsOn注解涉及到的創(chuàng)建Bean的流程涉及到DependsOnTest類(lèi)、AnnotationConfigApplicationContext類(lèi)、AbstractApplicationContext類(lèi)、DefaultListableBeanFactory類(lèi)和AbstractBeanFactory類(lèi)。具體的源碼執(zhí)行細(xì)節(jié)參見(jiàn)源碼解析部分。
五、源碼解析
源碼時(shí)序圖整清楚了,那就整源碼解析唄!
本節(jié),主要分析@DependsOn注解在Spring源碼層面的執(zhí)行流程,結(jié)合源碼執(zhí)行的時(shí)序圖,會(huì)理解的更加深刻。本節(jié),同樣會(huì)從注冊(cè)Bean、調(diào)用Bean工廠后置處理器和創(chuàng)建Bean三個(gè)方面分析源碼的執(zhí)行流程
5.1 注冊(cè)Bean的源碼流程
@DependsOn注解在Spring源碼層面注冊(cè)Bean的執(zhí)行流程,結(jié)合源碼執(zhí)行的時(shí)序圖,會(huì)理解的更加深刻,本節(jié)的源碼執(zhí)行流程可以結(jié)合圖7-1進(jìn)行理解。
(1)運(yùn)行案例程序啟動(dòng)類(lèi)
案例程序啟動(dòng)類(lèi)源碼詳見(jiàn):spring-annotation-chapter-07工程下的io.binghe.spring.annotation.chapter07.DependsOnTest,運(yùn)行DependsOnTest類(lèi)的main()方法。
在DependsOnTest類(lèi)的main()方法中調(diào)用了AnnotationConfigApplicationContext類(lèi)的構(gòu)造方法,并傳入了DependsOnConfig類(lèi)的Class對(duì)象來(lái)創(chuàng)建IOC容器。接下來(lái),會(huì)進(jìn)入AnnotationConfigApplicationContext類(lèi)的構(gòu)造方法。
(2)解析AnnotationConfigApplicationContext類(lèi)的AnnotationConfigApplicationContext(Class>... componentClasses)構(gòu)造方法
源碼詳見(jiàn):org.springframework.context.annotation.AnnotationConfigApplicationContext#AnnotationConfigApplicationContext(Class>... componentClasses)。
public AnnotationConfigApplicationContext(Class>... componentClasses) {
this();
register(componentClasses);
refresh();
}
可以看到,在上述構(gòu)造方法中,調(diào)用了register()方法來(lái)注冊(cè)Bean。
(3)解析AnnotationConfigApplicationContext類(lèi)的register(Class>... componentClasses) 方法
源碼詳見(jiàn):org.springframework.context.annotation.AnnotationConfigApplicationContext#register(Class>... componentClasses) 。
@Override
public void register(Class>... componentClasses) {
/************省略其他代碼***************/
this.reader.register(componentClasses);
registerComponentClass.end();
}
可以看到,在AnnotationConfigApplicationContext類(lèi)的register()方法中,調(diào)用reader對(duì)象的register()方法注冊(cè)Bean。
(4)解析AnnotatedBeanDefinitionReader類(lèi)的register(Class>... componentClasses)方法
源碼詳見(jiàn):org.springframework.context.annotation.AnnotatedBeanDefinitionReader#register(Class>... componentClasses)。
public void register(Class>... componentClasses) {
for (Class> componentClass : componentClasses) {
registerBean(componentClass);
}
}
可以看到,在AnnotatedBeanDefinitionReader類(lèi)的register()方法中,會(huì)循環(huán)遍歷傳入的componentClasses數(shù)組,并將遍歷出的每個(gè)componentClass元素作為參數(shù)調(diào)用registerBean()方法注冊(cè)Bean。
(5)解析AnnotatedBeanDefinitionReader類(lèi)的registerBean(Class> beanClass)方法
源碼詳見(jiàn):org.springframework.context.annotation.AnnotatedBeanDefinitionReader#registerBean(Class> beanClass)。
public void registerBean(Class> beanClass) {
doRegisterBean(beanClass, null, null, null, null);
}
可以看到,在AnnotatedBeanDefinitionReader類(lèi)的registerBean()方法中會(huì)調(diào)用doRegisterBean()方法來(lái)注冊(cè)Bean。
(6)解析AnnotatedBeanDefinitionReader類(lèi)的doRegisterBean(ClassbeanClass, String name, Class extends Annotation>[] qualifiers, Suppliersupplier, BeanDefinitionCustomizer[] customizers)方法
源碼詳見(jiàn):org.springframework.context.annotation.AnnotatedBeanDefinitionReader#doRegisterBean(ClassbeanClass, String name, Class extends Annotation>[] qualifiers, Suppliersupplier, BeanDefinitionCustomizer[] customizers)。重點(diǎn)關(guān)注如下代碼片段。
privatevoid doRegisterBean(Class beanClass, @Nullable String name, @Nullable Class extends Annotation>[] qualifiers, @Nullable Supplier supplier, @Nullable BeanDefinitionCustomizer[] customizers) {
/******************省略其他代碼**********************/
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
/******************省略其他代碼**********************/
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
可以看到,在AnnotatedBeanDefinitionReader類(lèi)的doRegisterBean()方法中,會(huì)調(diào)用AnnotationConfigUtils類(lèi)的processCommonDefinitionAnnotations()方法。
(7)解析AnnotationConfigUtils類(lèi)的processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd)方法
源碼詳見(jiàn):org.springframework.context.annotation.AnnotationConfigUtils#processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd)
public static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) {
processCommonDefinitionAnnotations(abd, abd.getMetadata());
}
可以看到,在AnnotationConfigUtils類(lèi)的processCommonDefinitionAnnotations()方法中調(diào)用了具有兩個(gè)參數(shù)的processCommonDefinitionAnnotations()方法。
(8)解析AnnotationConfigUtils類(lèi)的processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata)方法
源碼詳見(jiàn):org.springframework.context.annotation.AnnotationConfigUtils#processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata)。
static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);
if (lazy != null) {
abd.setLazyInit(lazy.getBoolean("value"));
}
else if (abd.getMetadata() != metadata) {
lazy = attributesFor(abd.getMetadata(), Lazy.class);
if (lazy != null) {
abd.setLazyInit(lazy.getBoolean("value"));
}
}
if (metadata.isAnnotated(Primary.class.getName())) {
abd.setPrimary(true);
}
AnnotationAttributes dependsOn = attributesFor(metadata, DependsOn.class);
if (dependsOn != null) {
abd.setDependsOn(dependsOn.getStringArray("value"));
}
AnnotationAttributes role = attributesFor(metadata, Role.class);
if (role != null) {
abd.setRole(role.getNumber("value").intValue());
}
AnnotationAttributes description = attributesFor(metadata, Description.class);
if (description != null) {
abd.setDescription(description.getString("value"));
}
}
可以看到,在processCommonDefinitionAnnotations()方法中,解析了@DependsOn注解,并將解析出的@DependsOn注解中的value屬性的值設(shè)置到AnnotatedBeanDefinition對(duì)象的dependsOn屬性中。
(9)回到AnnotatedBeanDefinitionReader類(lèi)的doRegisterBean(ClassbeanClass, String name, Class extends Annotation>[] qualifiers, Suppliersupplier, BeanDefinitionCustomizer[] customizers)方法。
在AnnotatedBeanDefinitionReader類(lèi)的doRegisterBean()方法中,會(huì)調(diào)用BeanDefinitionReaderUtils類(lèi)的registerBeanDefinition()方法,并將封裝了@DependsOn注解屬性的abd對(duì)象和beanName封裝成BeanDefinitionHolder對(duì)象,并且與registry一起作為參數(shù)傳遞給BeanDefinitionReaderUtils類(lèi)的registerBeanDefinition()方法。
(10)解析BeanDefinitionReaderUtils類(lèi)的registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)方法
源碼詳見(jiàn):org.springframework.beans.factory.support.BeanDefinitionReaderUtils#registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)。
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
String beanName = definitionHolder.getBeanName();
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
可以看到,在registerBeanDefinition()方法中,會(huì)調(diào)用DefaultListableBeanFactory類(lèi)的registerBeanDefinition()方法將BeanDefinition信息注冊(cè)到IOC容器中。
(11)解析DefaultListableBeanFactory類(lèi)的registerBeanDefinition(String beanName, BeanDefinition beanDefinition)方法
源碼詳見(jiàn):org.springframework.beans.factory.support.DefaultListableBeanFactory#registerBeanDefinition(String beanName, BeanDefinition beanDefinition)。重點(diǎn)關(guān)注如下代碼片段。
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
/*********省略其他代碼**********/
BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
if (existingDefinition != null) {
/*********省略其他代碼**********/
}
else {
/*********省略其他代碼**********/
else {
// Still in startup registration phase
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
removeManualSingletonName(beanName);
}
this.frozenBeanDefinitionNames = null;
}
/*********省略其他代碼**********/
}
可以看到,在DefaultListableBeanFactory類(lèi)的registerBeanDefinition()方法中,會(huì)將beanName為Key,beanDefinition對(duì)象作為Value保存到beanDefinitionMap中。
至此,@DependsOn注解涉及到的注冊(cè)Bean的源碼流程分析完畢。
5.2 調(diào)用Bean工廠后置處理器的源碼流程
@DependsOn注解在Spring源碼層面調(diào)用Bean工廠后置處理器的執(zhí)行流程,結(jié)合源碼執(zhí)行的時(shí)序圖,會(huì)理解的更加深刻,本節(jié)的源碼執(zhí)行流程可以結(jié)合圖7-2~7-4進(jìn)行理解。
注意:@DependsOn注解在Spring源碼層面調(diào)用Bean工廠后置處理器的執(zhí)行流程,執(zhí)行到ConfigurationClassParser類(lèi)的doProcessConfigurationClass()方法之前的邏輯與第5章解析@Import注解的代碼流程相同,這里不再贅述。后續(xù)的代碼流程直接從ConfigurationClassParser類(lèi)的doProcessConfigurationClass()方法開(kāi)始解析。
(1)解析ConfigurationClassParser類(lèi)的doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass, Predicatefilter)方法
源碼詳見(jiàn):org.springframework.context.annotation.ConfigurationClassParser#doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass, Predicatefilter),重點(diǎn)關(guān)注如下代碼片段。
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass, Predicatefilter) throws IOException {
/****************省略其他代碼****************/
SetcomponentScans = AnnotationConfigUtils.attributesForRepeatable(
sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
if (!componentScans.isEmpty() &&
!this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
for (AnnotationAttributes componentScan : componentScans) {
SetscannedBeanDefinitions =
this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
if (bdCand == null) {
bdCand = holder.getBeanDefinition();
}
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
parse(bdCand.getBeanClassName(), holder.getBeanName());
}
}
}
}
/****************省略其他代碼****************/
return null;
}
可以看到,在ConfigurationClassParser類(lèi)的doProcessConfigurationClass()方法中,會(huì)調(diào)用componentScanParser的parse()方法來(lái)解析配置類(lèi)上的注解。
(2)解析ComponentScanAnnotationParser類(lèi)的parse(AnnotationAttributes componentScan, String declaringClass)方法
源碼詳見(jiàn):org.springframework.context.annotation.ComponentScanAnnotationParser#parse(AnnotationAttributes componentScan, String declaringClass)。
public Setparse(AnnotationAttributes componentScan, String declaringClass) {
/***********省略其他代碼*************/
return scanner.doScan(StringUtils.toStringArray(basePackages));
}
可以看到,在ComponentScanAnnotationParser類(lèi)的parse()方法中,會(huì)調(diào)用scanner對(duì)象的doScan()方法掃描@ComponentScan注解中basePackages屬性設(shè)置的包名。
(3)解析ClassPathBeanDefinitionScanner類(lèi)中的doScan(String... basePackages)方法
源碼詳見(jiàn):org.springframework.context.annotation.ClassPathBeanDefinitionScanner#doScan(String... basePackages)。
protected SetdoScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
SetbeanDefinitions = new LinkedHashSet<>();
for (String basePackage : basePackages) {
Setcandidates = findCandidateComponents(basePackage);
for (BeanDefinition candidate : candidates) {
/************省略其他代碼************/
if (candidate instanceof AnnotatedBeanDefinition) {
AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
}
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
return beanDefinitions;
}
可以看到,在ClassPathBeanDefinitionScanner類(lèi)中的doScan()方法中,會(huì)調(diào)用AnnotationConfigUtils類(lèi)的processCommonDefinitionAnnotations()方法來(lái)解析注解的信息。后續(xù)的執(zhí)行流程與5.1節(jié)中源碼解析的步驟(7)~(8)相同,這里不再贅述。
另外,在ClassPathBeanDefinitionScanner類(lèi)中的doScan()方法中,會(huì)調(diào)用registerBeanDefinition()方法來(lái)注冊(cè)BeanDefinition信息。
(4)解析ClassPathBeanDefinitionScanner類(lèi)的registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)方法
源碼詳見(jiàn):org.springframework.context.annotation.ClassPathBeanDefinitionScanner#registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)。
protected void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) {
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, registry);
}
可以看到,在ClassPathBeanDefinitionScanner類(lèi)的registerBeanDefinition()方法中,直接調(diào)用了BeanDefinitionReaderUtils類(lèi)的registerBeanDefinition()方法來(lái)注冊(cè)BeanDefinition信息。
(5)解析BeanDefinitionReaderUtils類(lèi)的registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)方法
源碼詳見(jiàn):org.springframework.beans.factory.support.BeanDefinitionReaderUtils#registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)。
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)throws BeanDefinitionStoreException {
String beanName = definitionHolder.getBeanName();
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
/*********省略其他代碼************/
}
可以看到,在BeanDefinitionReaderUtils類(lèi)的registerBeanDefinition()方法中,最終就會(huì)調(diào)用DefaultListableBeanFactory類(lèi)的registerBeanDefinition()方法來(lái)注冊(cè)BeanDefinition信息。
至此,@DependsOn注解在Spring源碼層面調(diào)用Bean工廠后置處理器的執(zhí)行流程分析完畢。
5.3 創(chuàng)建Bean的源碼流程
@DependsOn注解在Spring源碼層面創(chuàng)建Bean的執(zhí)行流程,結(jié)合源碼執(zhí)行的時(shí)序圖,會(huì)理解的更加深刻,本節(jié)的源碼執(zhí)行流程可以結(jié)合圖7-5進(jìn)行理解。
注意:@DependsOn注解在Spring源碼層面創(chuàng)建Bean的執(zhí)行流程,執(zhí)行到AbstractApplicationContext類(lèi)的refresh()方法的邏輯,與第5章解析@Import注解執(zhí)行到AbstractApplicationContext類(lèi)的refresh()方法的邏輯相同,這里不再贅述。后續(xù)會(huì)直接從AbstractApplicationContext類(lèi)的refresh()方法開(kāi)始分析源碼。
(1)解析AbstractApplicationContext類(lèi)的refresh()方法
源碼詳見(jiàn):org.springframework.context.support.AbstractApplicationContext#refresh(),重點(diǎn)關(guān)注如下代碼片段。
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
/*********省略其他代碼************/
try {
/*********省略其他代碼************/
finishBeanFactoryInitialization(beanFactory);
/*********省略其他代碼************/
}
catch (BeansException ex) {
/*********省略其他代碼************/
}
finally {
/*********省略其他代碼************/
}
}
}
可以看到,在refresh()中會(huì)調(diào)用finishBeanFactoryInitialization()方法來(lái)完成非懶加載的單實(shí)例Bean的初始化工作。
(2)解析finishBeanFactoryInitialization類(lèi)的finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory)方法
源碼詳見(jiàn):org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory)。
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
/*******省略其他代碼*******/
beanFactory.preInstantiateSingletons();
}
可以看到,在finishBeanFactoryInitialization類(lèi)的finishBeanFactoryInitialization()方法中,會(huì)調(diào)用beanFactory對(duì)象的preInstantiateSingletons()方法來(lái)初始化所有的非懶加載的單實(shí)例Bean。
(3)解析DefaultListableBeanFactory類(lèi)的preInstantiateSingletons()方法
源碼詳見(jiàn):org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons()。重點(diǎn)關(guān)注如下代碼片段。
@Override
public void preInstantiateSingletons() throws BeansException {
/*********省略其他代碼*********/
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof SmartFactoryBean> smartFactoryBean && smartFactoryBean.isEagerInit()) {
getBean(beanName);
}
}
else {
getBean(beanName);
}
}
}
/*********省略其他代碼*********/
}
可以看到,在DefaultListableBeanFactory類(lèi)的preInstantiateSingletons()方法中,會(huì)遍歷beanDefinitionNames集合中所有的beanName,并調(diào)用getBean()方法初始化所有非懶加載的單實(shí)例Bean。
(4)解析AbstractBeanFactory類(lèi)的getBean(String name)方法
源碼詳見(jiàn):org.springframework.beans.factory.support.AbstractBeanFactory#getBean(String name)。
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
可以看到,在AbstractBeanFactory類(lèi)的getBean()方法中,直接調(diào)用了doGetBean()方法來(lái)初始化非懶加載的單實(shí)例Bean。
(5)解析AbstractBeanFactory類(lèi)的doGetBean(String name, ClassrequiredType, Object[] args, boolean typeCheckOnly)方法
源碼詳見(jiàn):org.springframework.beans.factory.support.AbstractBeanFactory#doGetBean(String name, ClassrequiredType, Object[] args, boolean typeCheckOnly)。重點(diǎn)關(guān)注如下代碼片段。
protectedT doGetBean(String name, @Nullable Class requiredType, @Nullable Object[] args, boolean typeCheckOnly) throws BeansException {
/*************省略其他代碼**************/
else {
/*************省略其他代碼**************/
try {
/*************省略其他代碼**************/
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dep : dependsOn) {
if (isDependent(beanName, dep)) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");
}
registerDependentBean(dep, beanName);
try {
getBean(dep);
}
catch (NoSuchBeanDefinitionException ex) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName,
"'" + beanName + "' depends on missing bean '" + dep + "'", ex);
}
}
}
/*************省略其他代碼**************/
}
catch (BeansException ex) {
beanCreation.tag("exception", ex.getClass().toString());
beanCreation.tag("message", String.valueOf(ex.getMessage()));
cleanupAfterBeanCreationFailure(beanName);
throw ex;
}
finally {
beanCreation.end();
}
}
return adaptBeanInstance(name, beanInstance, requiredType);
}
可以看到,在AbstractBeanFactory類(lèi)的doGetBean()方法中,會(huì)獲取這些被依賴(lài)的beanName,按照數(shù)組順序,再調(diào)用AbstractBeanFactory類(lèi)的getBean()方法來(lái)優(yōu)先創(chuàng)建被依賴(lài)的Bean,從而達(dá)到控制依賴(lài)順序的目的。
另外,在創(chuàng)
當(dāng)前名稱(chēng):深度解析@DependsOn注解
瀏覽地址:http://fisionsoft.com.cn/article/dhsojgs.html


咨詢
建站咨詢
