关键词:
1 springboot在启动的时候,会调用run方法,创建环境设置spring容器,其中包含refresh方法,完成配置类解析,各种beanFactoryPostProcess和beanPostProcessor注册,web内置容器构造,国际化配置初始化等,refresh调用了父类AbstractApplicationContext的refresh方法如下。
public void refresh() throws BeansException, IllegalStateException {
Object var1 = this.startupShutdownMonitor;
synchronized(this.startupShutdownMonitor) {
this.prepareRefresh();
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
this.prepareBeanFactory(beanFactory);
try {
this.postProcessBeanFactory(beanFactory);
this.invokeBeanFactoryPostProcessors(beanFactory);
this.registerBeanPostProcessors(beanFactory);
this.initMessageSource();
this.initApplicationEventMulticaster();
this.onRefresh();
this.registerListeners();
this.finishBeanFactoryInitialization(beanFactory);
this.finishRefresh();
} catch (BeansException var9) {
if(this.logger.isWarnEnabled()) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
}
this.destroyBeans();
this.cancelRefresh(var9);
throw var9;
} finally {
this.resetCommonCaches();
}
}
}
(1)prepareRefresh 在rehresh之前做的准备工作,一是设置spring启动事件,开启活跃状态;二是初始化属性源信息;三是验证必要属性。
(2)prepareBeanFactory 从spring容器获取BeanFactory并进行相关设置为后续使用做准备。
*设置用于加载bean的classLoader,设置可以解析bean表达式的表达式解析器,添加属性注册器ResourceEditorRegistrar。
* 添加ApplicationContextAwarePocessor这个BeanPostProcessor,注入ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware、EnvironmentAware几个接口。
* 设置各种bean,BeanFactory,ResourceLoader,ApplicatioinEventPublisher,ApplicationContext。
* 配置默认系统属性等。
(3)postProcessBeanFactory 继上一步beanfactory设置之后进行后续操作,不同spring容器进行不同操作。比如AnnotationConfigEmbeddedWebApplicationContext会对bean进行注入,检查basePackages属性,如果设置了会使用ClassPathBeanDefinitionScanner对basePackage下面的bean进行扫描并注册,如果设置了annotatedClasses属性,就会使用AnnotatedBeanDefinitionReader注册这些带注解的bean。
(4)invokeBeanFactoryPostProcessors
* BeanFactoryPostProcessor 其实现类可以在spring容器加载了bean的定义文件之后,在bean实例化之前执行。接口方法的入参是ConfigurrableListableBeanFactory,使用该参数,可以获取到相关bean的定义信息,修改各种配置的元数据,可以配置多个processor,通过设置order属性来控制各个实现类的执行顺序。
* BeanPostProcessor BeanPostProcessor是在spring容器加载了bean的定义文件并且实例化bean之后执行的。BeanPostProcessor的执行顺序是在BeanFactoryPostProcessor之后,BeanPostProcessor的作用域是容器级的,它只和所在容器有关。如果你在容器中定义了BeanPostProcessor,它仅仅对此容器中的bean进行后置。它不会对定义在另一个容器中的bean进行任何处理。
* BeanDefinitionRegistryPostProcessor:继承BeanFactoryPostProcessor,作用跟BeanFactoryPostProcessor一样,只不过是使用BeanDefinitionRegistry对bean进行处理
基于web程序的Spring容器AnnotationConfigEmbeddedWebApplicationContext构造的时候,会初始化内部属性AnnotatedBeanDefinitionReader reader,这个reader构造的时候会在BeanFactory中注册一些post processor,包括BeanPostProcessor和BeanFactoryPostProcessor(比如ConfigurationClassPostProcessor、AutowiredAnnotationBeanPostProcessor);invokeBeanFactoryPostProcessors方法处理BeanFactoryPostProcessor的逻辑是:
从Spring容器中找出BeanDefinitionRegistryPostProcessor类型的bean(这些processor是在容器刚创建的时候通过构造AnnotatedBeanDefinitionReader的时候注册到容器中的),然后按照优先级分别执行,优先级的逻辑如下:
1)实现PriorityOrdered接口的BeanDefinitionRegistryPostProcessor先全部找出来,然后排序后依次执行
2)实现Ordered接口的BeanDefinitionRegistryPostProcessor找出来,然后排序后依次执行
3)没有实现PriorityOrdered和Ordered接口的BeanDefinitionRegistryPostProcessor找出来执行并依次执行
ConfigurationClassPostProcessor这个processor是优先级最高的被执行的processor(实现了PriorityOrdered接口)。这个ConfigurationClassPostProcessor会去BeanFactory中找出所有有@Configuration注解的bean,然后使用ConfigurationClassParser去解析这个类。ConfigurationClassParser内部有个Map类型的configurationClasses属性用于保存解析的类,ConfigurationClass是一个对要解析的配置类的封装,内部存储了配置类的注解信息、被@Bean注解修饰的方法、@ImportResource注解修饰的信息、ImportBeanDefinitionRegistrar等都存储在这个封装类中。这里ConfigurationClassPostProcessor最先被处理还有另外一个原因是如果程序中有自定义的BeanFactoryPostProcessor,那么这个PostProcessor首先得通过ConfigurationClassPostProcessor被解析出来,然后才能被Spring容器找到并执行。(ConfigurationClassPostProcessor不先执行的话,这个Processor是不会被解析的,不会被解析的话也就不会执行了)。
invokeBeanFactoryPostProcessors方法总结来说就是从Spring容器中找出BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor接口的实现类并按照一定的规则顺序进行执行。 其中ConfigurationClassPostProcessor这个BeanDefinitionRegistryPostProcessor优先级最高,它会对项目中的@Configuration注解修饰的类(@Component、@ComponentScan、@Import、@ImportResource修饰的类也会被处理)进行解析,解析完成之后把这些bean注册到BeanFactory中。需要注意的是这个时候注册进来的bean还没有实例化。
(5)registerBeanPostProcessors
使用了PostProcessorRegistrationDelegate类的registerBeanPostProcessors方法执行。这里的过程跟invokeBeanFactoryPostProcessors类似:
1)先找出实现了PriorityOrdered接口的BeanPostProcessor并排序后加到BeanFactory的BeanPostProcessor集合中
2)找出实现了Ordered接口的BeanPostProcessor并排序后加到BeanFactory的BeanPostProcessor集合中
3)没有实现PriorityOrdered和Ordered接口的BeanPostProcessor加到BeanFactory的BeanPostProcessor集合中
这些已经存在的BeanPostProcessor在postProcessBeanFactory方法中已经说明,都是由AnnotationConfigUtils的registerAnnotationConfigProcessors方法注册的。这些BeanPostProcessor包括有AutowiredAnnotationBeanPostProcessor(处理被@Autowired注解修饰的bean并注入)、RequiredAnnotationBeanPostProcessor(处理被@Required注解修饰的方法)、CommonAnnotationBeanPostProcessor(处理@PreDestroy、@PostConstruct、@Resource等多个注解的作用)等。如果是自定义的BeanPostProcessor,已经被ConfigurationClassPostProcessor注册到容器内。
这些BeanPostProcessor会在这个方法内被实例化(通过调用BeanFactory的getBean方法,如果没有找到实例化的类,就会去实例化)。
(6)initMessageSource 初始化国际化属性。
(7)initApplicationEventMulticaster 初始化事件广播器,用于发布事件。EventPublishingRunlistener会监听事件,在run函数之前contextPrepared时候已经注入了。这个时候不需要注册,只要拿到BeanFactory的广播器直接设置到spring容器,如果没有再自己初始化。
(8)onRefresh 不同容器各自实现,比如ConfigEmbeddedWebApplicationContext中会调用createEmbeddedServletContainer方法去创建内置的Servlet容器,目前只支持三种 tomcat,jetty,undertow。
(9)registerListeners 把spring容器内的listener和beanfactory的listener都添加到广播器中。
(10)finishBeanFactoryInitialization 实例化BeanFactory 中已经被注册但是没被实例化的所有实例,懒加载除外。比如invokeBeanFactoryPostProcessors方法中根据各种注解解析出来的类,都会初始化。初始化的过程中各种BeanPostProcessor开始起作用。
(11)finishRefresh 初始化生命周期处理器LifecycleProcessor并调用其onrefresh方法,找到SmartLifecycle接口的所有实现类并调用start方法,发布事件告知listener,如果设置了JMX相关属性,还会调用LiveBeansView的registerApplicationContext方法。
springboot启动流程ioc容器refresh过程(上篇)
所有文章https://www.cnblogs.com/lay2017/p/11478237.html 正文在前面的几篇文章中,我们看到Environment创建、application配置文件的加载、ApplicationContext实例对象的创建、以及主类加载成为BeanDefinition。做了这么多的准备,终于到了核心的... 查看详情
springboot与tomcat的启动(内嵌tomcat)
参考技术A环境:SpringBoot2.0.1使用SpringBoot开发时,可以通过Maven将工程打成jar包,jar包内嵌Tomcat,这种方式SpringBoot工程将在启动的时候,带动Tomcat的启动,下面分析SpringBoot如何带动Tomcat启动一个简单的SpringBoot工程启动类跟进Sprin... 查看详情
记一次启动springboot失败的问题
参考技术A在开发SpringBoot项目的时候,启动项目,启动失败,提示如下,只截取关键部分:该异常的Description只是表面现象,而不是根本原因,要想知道根本原因,就需要查看是否之前就抛出了其他异常。正是更早的异常导致Sprin... 查看详情
springboot的启动过程及部分注解
参考技术A相比于以前繁琐的基于Spring的Web应用,SpringBoot通过默认配置很多框架的方式,极大的简化了项目的搭建以及开发流程。一个简单的SpringBoot应用只需要三步:1.在pom.xml中引入所需要的依赖2.在application.yml配置所需的数据... 查看详情
springboot启动分析
...初始化过程的三个步骤。 第一步:Resource定位 在SpringBoot中,我们都知道他的包扫描是从主类所在的包开始扫描的,prepareContext()方法中,会先将主类解析成BeanDefinition,然后在refresh()方法的invokeBeanFactoryPostProcessors()方法中... 查看详情
springboot启动过程原理
最近这两年springboot突然火起来了,那么我们就来看看springboot的运行原理。一。springboot的三种启动方式:1.运行带有main方法的2.通过命令Java-jar命令3.通过spring-boot-plugin的方式二。springboot启动时执行方法,有两种方式第一种方式... 查看详情
使用 SpringBoot 2 自动化 OAuth2 refresh_token 过程
】使用SpringBoot2自动化OAuth2refresh_token过程【英文标题】:automatetheOAuth2refresh_tokenprocesswithSpringBoot2【发布时间】:2022-01-0203:56:16【问题描述】:我有一个SpringBoot2应用程序,一个作为resource-server的MainApp,作为AuthorizationServer的KeyCloa... 查看详情
涨姿势:springboot2.x启动全过程源码分析
目录SpringApplication实例run方法运行过程总结上篇《SpringBoot2.x启动全过程源码分析(一)入口类剖析》我们分析了SpringBoot入口类SpringApplication的源码,并知道了其构造原理,这篇我们继续往下面分析其核心run方法。SpringApplication实... 查看详情
springboot启动过程:springapplication及springapplicationbuilder
SpringBoot应用的启动是基于SpringApplication类的,下面一步步地分析。构造方法及初始化其构造方法有二,都调用了initialize方法,完成注解源的配置。 publicSpringApplication(Object...sources) initialize(sources); publicSpringApplication(R 查看详情
springboot启动过程-初始化
1 springboot启动时,只需要调用一个类前面加了@SpringBootApplication的main函数,执行SpringApplication.run(DemoApplication.class,args)即可,这里初始化了一个SpringApplication实例,然后调用run启动springboot。run方法中,调用了initialize,如下@Suppr... 查看详情
quartz与spring集成——启动调度器
...动过程。熟悉Spring原理的人都知道AbstractApplicationContext的refresh方法的重要性,在refresh方法中调用了finishRefresh方法,最后会调用到SchedulerFactoryBean的start方法,其调用栈如图1所示。图1 SchedulerFact 查看详情
springboot启动过程
写过SpringBoot都知道需要有一个入口类,这个类上面必不可上的需要有一个@SpringBootApplication注解还有run方法,下面我们讲一下他们。@SpringBootApplication点击进入该注解,我们可以发现其是一个复合注解,包括@SpringBootConfiguration、@En... 查看详情
跟跟springboot启动容器,自动装配的过程
...习------------------------------------------------------------运行被@SpringBootApplication修饰的程序入口,执行main方法,调用SpringAppl 查看详情
springboot启动流程
...法里面new一个SpringApplication对象,传入bean源,就是注解了SpringBootApplication的那个类,调用run方法。springboot启动流程分为两部分一部分是准备阶段,一部分是运行阶段准备阶段主要有这么几步:1、配置bean的源,就是bean的来源,... 查看详情
springboot启动过程:springapplication及springapplicationbuilder(代码片段)
SpringBoot应用的启动是基于SpringApplication类的,下面一步步地分析。构造方法及初始化其构造方法有二,都调用了initialize方法,完成注解源的配置。 publicSpringApplication(Object...sources) initialize(sources); publicSpringApplication(Res... 查看详情
springboot启动过程:springapplication及springapplicationbuilder(代码片段)
SpringBoot应用的启动是基于SpringApplication类的,下面一步步地分析。构造方法及初始化其构造方法有二,都调用了initialize方法,完成注解源的配置。 publicSpringApplication(Object...sources) initialize(sources); publicSpringApplication(Res... 查看详情
springboot启动流程
springboot版本为:2.2.3概述springboot的启动过程主要是两个方面,一个是创建SpringApplication这个类,该类用于启动启动整个应用,是应用的启动类。另一方面是SpringApplication的run方法,该方法会初始化listener和initialize,并在分发事件到... 查看详情
启动springboot报错,怎么解决
【解决办法】需要在启动类的@EnableAutoConfiguration或@SpringBootApplication中添加exclude=DataSourceAutoConfiguration.class,排除此类的autoconfig。启动以后就可以正常运行。【原因】这个原因是maven依赖包冲突,有重复的依赖。【Spring Boo... 查看详情