java回调spring接口_Spring Boot启动过程及回调接口汇总

启动顺序

Spring boot的启动代码一般是这样的:

1

2

3

4

5

6@SpringBootApplication

public class SampleApplication {

public static void main(String[] args)throws Exception {

SpringApplication.run(SampleApplication.class, args);

}

}

初始化SpringApplication

1、SpringApplication#run(Object source, String... args)#L1174

2、SpringApplication#L1186 -> SpringApplication(sources)#L236

3、SpringApplication#initialize(Object[] sources)#L256 javadoc

4、SpringApplication#L257 添加source(复数),SpringApplication使用source来构建Bean。一般来说在run的时候都会把@SpringBootApplication标记的类(本例中是SampleApplication)放到sources参数里,然后由这个类出发找到Bean的定义。

7、SpringApplication#L1186 -> SpringApplication#run(args)#L297,进入运行阶段

推送ApplicationStartedEvent

SpringApplication#run(args)#L297

准备Environment

SpringApplication#run(args)#L297->#L308->prepareEnvironment(...)#L331准备ConfigurableEnvironment。

创建及准备ApplicationContext

SpringApplication#run(args)#L297

5、SpringApplication#L348->postProcessApplicationContext(context)#L605,给ApplicationContext设置了一些其他东西

8、SpringApplication#L366->load#L687,负责将source(复数)里所定义的Bean加载到ApplicationContext里,在本例中就是SampleApplication,这些source是在初始化SpringApplication阶段获得的。

要注意的是在这个阶段,ApplicationContext里只有SampleApplication,SampleApplication是Bean的加载工作的起点。

刷新ApplicationContext

SpringApplication#run(args)#L297 ->#L315->SpringApplication#refreshContext(context)#L370 ->#L371->SpringApplication#refresh(context)#L759 ->#L761->AbstractApplicationContext#refreshAbstractApplicationContext#L507

1、AbstractApplicationContext#L510->AbstractApplicationContext#prepareRefresh()#L575,做了一些初始化工作,比如设置了当前Context的状态,初始化propertySource(其实啥都没干),检查required的property是否都已在Environment中(其实并没有required的property可供检查)等。

4、给beanFactory设置了ClassLoader

5、给beanFactory设置了SpEL解析器

11、把getEnvironment()作为Bean添加到beanFactory中,Bean Name: environment

12、把getEnvironment().getSystemProperties()作为Bean添加到beanFactory中,Bean Name: systemProperties

13、把getEnvironment().getSystemEnvironment()作为Bean添加到beanFactory中,Bean Name: systemEnvironment

14、AbstractApplicationContext#L520->postProcessBeanFactory(beanFactory),后置处理BeanFactory,实际啥都没做

25、AbstractApplicationContext#L541->finishBeanFactoryInitialization#L828。注意#L861,在这一步的时候才会实例化所有non-lazy-init bean,这里说的实例化不只是new而已,注入、BeanPostProcessor都会执行。

调用 ApplicationRunner 和 CommandLineRunner

SpringApplication#run(args)#L297 ->afterRefresh(context, applicationArguments)#L316 ->callRunners(context, args)#L771 ->#L774 先后调用了当前ApplicationContext中的ApplicationRunner和CommandLineRunner。关于它们的相关文档可以看这里。

需要注意的是,此时的ApplicationContext已经刷新完毕了,该有的Bean都已经有了。

推送ApplicationReadyEvent or ApplicationFailedEvent

SpringApplication#run(args)#L297->listeners.finished(context, null)#L317 间接地调用了EventPublishingRunListener#getFinishedEventEventPublishingRunListener#L96,发送了ApplicationReadyEvent或ApplicationFailedEvent回调接口

ApplicationContextInitializer

加载方式:读取classpath*:META-INF/spring.factories中key等于org.springframework.context.ApplicationContextInitializer的property列出的类

已知清单1:spring-boot-1.4.1.RELEASE.jar!/META-INF/spring.factories

2、ContextIdApplicationContextInitializer(优先级:Ordered.LOWEST_PRECEDENCE – 10)

已知清单2:spring-boot-autoconfigure-1.4.1.RELEASE.jar!/META-INF/spring.factories

ApplicationListener

加载方式:读取classpath*:META-INF/spring.factories中key等于org.springframework.context.ApplicationListener的property列出的类

已知清单1:spring-boot-1.4.1.RELEASE.jar!/META-INF/spring.factories中定义的

1、ClearCachesApplicationListener(优先级:无=Ordered.LOWEST_PRECEDENCE)

2、ParentContextCloserApplicationListener(优先级:Ordered.LOWEST_PRECEDENCE – 10)

3、FileEncodingApplicationListener(优先级:Ordered.LOWEST_PRECEDENCE)

4、AnsiOutputApplicationListener(优先级:ConfigFileApplicationListener.DEFAULT_ORDER + 1)

5、ConfigFileApplicationListener(优先级:Ordered.HIGHEST_PRECEDENCE + 10)

8、ClasspathLoggingApplicationListener(优先级:LoggingApplicationListener的优先级 + 1)

9、LoggingApplicationListener(优先级:Ordered.HIGHEST_PRECEDENCE + 20)

已知清单2:spring-boot-autoconfigure-1.4.1.RELEASE.jar!/META-INF/spring.factories中定义的

SpringApplicationRunListener

加载方式:读取classpath*:META-INF/spring.factories中key等于org.springframework.boot.SpringApplicationRunListener的property列出的类

已知清单:spring-boot-1.4.1.RELEASE.jar!/META-INF/spring.factories定义的

1、org.springframework.boot.context.event.EventPublishingRunListener(优先级:0)

EnvironmentPostProcessor

加载方式:读取classpath*:META-INF/spring.factories中key等于org.springframework.boot.env.EnvironmentPostProcessor的property列出的类

已知清单:spring-boot-1.4.1.RELEASE.jar!/META-INF/spring.factories定义的

1、CloudFoundryVcapEnvironmentPostProcessor(优先级:ConfigFileApplicationListener.DEFAULT_ORDER – 1)

BeanPostProcessor

用来对Bean实例进行修改的勾子,根据Javadoc ApplicationContext会自动侦测到BeanPostProcessor Bean,然后将它们应用到后续创建的所有Bean上。

BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor

*Aware

*Aware是一类可以用来获得Spring对象的interface,这些interface都继承了Aware,已知的有:

@Configuration 和 Auto-configuration

这两者的相同之处有:

都可以使用@Condition*来根据情况选择是否加载

而不同之处有:

1、加载方式不同:普通@Configuration则是通过扫描package path加载的

Auto-configuration的是通过读取classpath*:META-INF/spring.factories中key等于org.springframework.boot.autoconfigure.EnableAutoConfiguration的property列出的@Configuration加载的

2、加载顺序不同:普通@Configuration的加载在Auto-configuration之前,但是有例外情况,看下面。

3、内部加载顺序可控上的不同:

1、Auto-configuration如果出现在最初的扫描路径里(@ComponentScan),就会被提前加载到,然后被当作普通的@Configuration处理,这样@AutoConfigureBefore和@AutoConfigureAfter就没用了。参看例子代码里的InsideAutoConfiguration和InsideAutoConfiguration2。

2、Auto-configuration如果提供BeanPostProcessor,那么它会被提前加载。参见例子代码里的BeanPostProcessorAutoConfiguration。

4、Auto-configuration如果使用了ImportSelector,那么ImportSelector会被提前加载。参见例子代码里的UselessDeferredImportSelectorAutoConfiguration。

AnnotatedBeanDefinitionReader

ConfigurationClassPostProcessor

需要注意一个烟雾弹:看#L296->ConfigurationClassUtils#L209。而order的值则是在ConfigurationClassUtils#L122从注解中提取的。 这段代码似乎告诉我们它会对@Configuration进行排序,然后按次序加载。 实际上不是的,@Configuration是一个递归加载的过程。在本例中,是先从SampleApplication开始加载的,而事实上在这个时候,也就只有SampleApplication它自己可以提供排序。 而之后则直接使用了ConfigurationClassParser,它里面并没有排序的逻辑。

关于排序的方式简单来说是这样的:@Configuration的排序根据且只根据@Order排序,如果没有@Order则优先级最低。

ConfigurationClassParser

下面讲以下加载的顺序:

1、以SampleApplication为起点开始扫描

4、如果使用的是ImportSelector,则递归导入

顺带一提,如果Auto-configuration里再使用DeferredImportSelector,那么效果和使用ImportSelector效果是一样的,不会再被延后处理。参见例子代码里的UselessDeferredImportSelectorAutoConfiguration。

EnableAutoConfigurationImportSelector

1、先根据类名排序

内置类说明

LoggingApplicationListener

LoggingApplicationListener用来配置日志系统的,比如logback、log4j。Spring boot对于日志有详细解释,如果你想自定义日志配置,那么也请参考本文中对于LoggingApplicationListener的被调用时机的说明以获得更深入的了解。

StandardEnvironment

ConfigFileApplicationListener

ApplicationContextAwareProcessor

AnnotationConfigApplicationContext

根据javadoc,这个类用来将@Configuration和@Component作为输入来注册BeanDefinition。

特别需要注意的是,在javadoc中讲到其支持@Bean的覆盖:In case of multiple @Configuration classes, @Bean methods defined in later classes will override those defined in earlier classes. This can be leveraged to deliberately override certain bean definitions via an extra @Configuration class.

AnnotatedBeanDefinitionReader

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值