简介
本文介绍SpringBoot的启动流程。
分析Spring的启动流程有多种方法:1.构造一个 AnnotationConfigApplicationContext对象,调用它的getBean(xxx.class)方法; 2.直接分析SpringBoot的启动流程。
本文直接分析SpringBoot的启动流程。本文分析的版本:SpringBoot版本:2.3.0.RELEASE(其对应Spring:5.2.6.RELEASE)。
总流程概述
简介
- 从spring.factories配置文件中加载EventPublishingRunListener对象
- 该对象有SimpleApplicationEventMulticaster属性,它在SpringBoot启动过程的不同阶段用来发射内置的生命周期事件;
spring.factories位置:spring-boot-2.3.0.RELEASE.jar。
本处用到的是:
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener
- 该对象有SimpleApplicationEventMulticaster属性,它在SpringBoot启动过程的不同阶段用来发射内置的生命周期事件;
- 准备环境变量(Environment)
- 包括系统变量,环境变量,命令行参数,默认变量,servlet相关配置变量,随机值以及配置文件(比如application.properties)等;
- 打印SpringBoot的banner标志;
- 根据不同类型环境创建不同类型的ApplicationContext容器
- 因为这里是servlet环境,所以创建的是AnnotationConfigServletWebServerApplicationContext容器对象;
- 加载报告SpringBoot启动过程中的异常的对象;
- 从spring.factories配置文件中加载FailureAnalyzers对象,
- 为刚创建的容器对象做一些初始化工作,准备一些容器属性值等;
- 对ApplicationContext调用一些相关的后置处理
- 调用各个ApplicationContextInitializer的初始化方法来执行一些初始化逻辑等;
- 刷新容器。这一步至关重要。
- 调用BeanFactoryPostProcessor(BeanFactory的后置处理器))
- 注册并实例化BeanPostProcessor(bean的后置处理器)
- 初始化事件广播器(用于发布事件)
- 注册事件监听器(用于接收事件)
- 注册实现了ApplicationListener的bean
- 初始化其余的单例bean(调用到BeanPostProcessor)
- “其余的”的含义:BeanPostProcessor之外的bean,因为BeanPostProcessor在前边已经实例化,此处不再处理。
- 结束refresh
- 清除缓存(比如扫描到的ASM元数据信息)
- 初始化LifecycleProcessor并调用它的onRefresh()方法
- 发布刷新结束事件
- 执行刷新容器后的后置处理逻辑,注意这里为空方法;
- 调用ApplicationRunner和CommandLineRunner的run方法
- 我们实现这两个接口可以在Spring容器启动后执行一些操作
- 报告启动异常
- 若启动过程中抛出异常,此时用FailureAnalyzers来报告异常;
- 最终返回容器对象,这里调用方法没有声明对象来接收。
源码分析
SpringApplication.run(DemoApplication.class, args); //DemoApplication.class
run(new Class[]{primarySource}, args); //SpringApplication.class
(new SpringApplication(primarySources)).run(args); //SpringApplication.class
public ConfigurableApplicationContext run(String… args) //SpringApplication.class
public ConfigurableApplicationContext run(String... args) { // new 一个StopWatch用于统计run启动过程花了多少时间 StopWatch stopWatch = new StopWatch(); // 开始计时 stopWatch.start(); ConfigurableApplicationContext context = null; // exceptionReporters集合存储异常报告器,用来报告SpringBoot启动过程的异常 Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList(); // 配置“java.awt.headless”属性,默认true。即:即使没有检测到显示器,也允许其启动。 // 对于服务器来说,是不需要显示器的,所以要这样设置. this.configureHeadlessProperty(); // 【1】从spring.factories文件中找出key为ApplicationContextInitializer的类并实例化,然后赋值 // 给SpringApplicationRunListeners。目前里边只有:EventPublishingRunListener, // 它发射SpringBoot启动过程中内置的生命周期事件,标志不同启动阶段 SpringApplicationRunListeners listeners = this.getRunListeners(args); //发布【ApplicationStartingEvent】事件。 listeners.starting(); Collection exceptionReporters; try { // 创建ApplicationArguments对象,封装了args参数 ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); // 【2】准备环境变量:系统变量,环境变量,命令行参数,默认变量,servlet相关配置变量,随机值, // JNDI属性值,以及配置文件(比如application.properties)等,注意这些环境变量是有优先级的 // 发布【ApplicationEnvironmentPreparedEvent】事件 ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments); // 配置spring.beaninfo.ignore属性,默认为true,即跳过搜索BeanInfo classes. this.configureIgnoreBeanInfo(environment); // 【3】控制台打印SpringBoot的banner标志 Banner printedBanner = this.printBanner(environment); // 【4】创建不同类型的Spring ApplicationContext容器(根据类型) // 这里我引入web包,所以创建的是AnnotationConfigServletWebServerApplicationContext容器对象 context = this.createApplicationContext(); // 【5】从spring.factories中加载异常报告器实例,这里加载的是FailureAnalyzers。 // FailureAnalyzers构造参数为ConfigurableApplicationContext,因为要获取beanFactory和environment exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context); // 【6】为刚创建的容器对象做一些初始化工作,准备一些容器属性值等 // 1)为容器对象的属性AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner设置environgment属性 // 2)根据情况对ApplicationContext应用一些相关的后置处理,比如设置resourceLoader属性等 // 3)容器刷新前调用各个ApplicationContextInitializer的初始化方法,ApplicationContextInitializer是在 // 构建SpringApplication对象时从spring.factories中加载的 // 4)发布【ApplicationContextInitializedEvent】事件。标志context容器被创建且已准备好 // 5)从context容器获取beanFactory,向beanFactory中注册一些单例bean,比如applicationArguments,printedBanner // 6)TODO 加载bean到application context,注意这里只是加载了部分bean比如mainApplication这个bean, // 猜测:大部分bean是在AbstractApplicationContext.refresh方法中被加载 // 7)发布【ApplicationPreparedEvent】事件。标志Context容器已经准备完成 this.prepareContext(context, environment, listeners, applicationArguments, printedBanner); // 【7】刷新容器,这一步至关重要,主要做了以下工作: // 1)在context刷新前做一些准备工作,比如初始化一些属性设置,属性合法性校验和保存容器中的一些早期事件等; // 2)让子类刷新其内部bean factory,注意SpringBoot和Spring启动的情况执行逻辑不一样 // 3)对bean factory进行配置,比如配置bean factory的类加载器,后置处理器等 // 4)准备完bean factory后,执行后置处理逻辑,子类重写此方法在BeanFactory创建并预准备完成后做进一步设置 // 在这一步,所有的bean definitions将会被加载,但此时bean还不会被实例化 // 5)执行BeanFactoryPostProcessor的方法即调用bean factory的后置处理器: // BeanDefinitionRegistryPostProcessor(触发时机:bean定义的注册之前) // BeanFactoryPostProcessor(触发时机:bean定义的注册之后,bean实例化之前) // 6)注册bean后置处理器BeanPostProcessor。不同接口类型的BeanPostProcessor在Bean创建前后的执行时机不一样 // 7)初始化国际化MessageSource相关的组件,比如消息绑定,消息解析等 // 8)初始化事件广播器,若bean factory没包含事件广播器, // 则new一个SimpleApplicationEventMulticaster广播器对象并注册到bean factory中 // 9)AbstractApplicationContext定义了一个模板方法onRefresh,留给子类覆写。 // 比如ServletWebServerApplicationContext覆写了该方法来创建内嵌的tomcat容器 // 10)注册ApplicationListener接口的实现类,之前已经有了事件广播器,此时即可发布early application events // 11)完成容器bean factory的初始化,并初始化所有剩余的单例bean。 // 这一步非常重要,一些BeanPostProcessor会在这里调用。 // 12)完成容器的刷新工作,并且调用生命周期处理器的onRefresh()方法,并且发布ContextRefreshedEvent事件 this.refreshContext(context); // 【8】执行刷新容器后的后置处理逻辑。目前这里为空方法 this.afterRefresh(context, applicationArguments); // 停止stopWatch计时 stopWatch.stop(); // 打印日志 if (this.logStartupInfo) { (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch); } // 发布【ApplicationStartedEvent】事件。标志spring容器已经刷新,此时所有的bean实例都已经加载完毕 listeners.started(context); // 【9】调用ApplicationRunner和CommandLineRunner的run方法。 this.callRunners(context, applicationArguments); } catch (Throwable var10) { // 【10】若启动过程中抛出异常,此时用FailureAnalyzers来报告异常 // 并发布【ApplicationFailedEvent】事件,标志SpringBoot启动失败 this.handleRunFailure(context, var10, exceptionReporters, listeners); throw new IllegalStateException(var10); } try { // 发布【ApplicationReadyEvent】事件。标志SpringApplication已在运行(即已经成功启动),可以接收服务请求了。 listeners.running(context); // 【11】最终返回容器 return context; } catch (Throwable var9) { // 若出现异常,此时仅仅报告异常,而不会发射任何事件 this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null); throw new IllegalStateException(var9); } }
refresh()简述
在上边“总流程概述”中,this.refreshContext(context);是关键,追踪它:
this.refreshContext(context); //SpringApplication.class
this.refresh((ApplicationContext)context); // SpringApplication.class
this.refresh((ConfigurableApplicationContext)applicationContext); //SpringApplication.class
applicationContext.refresh(); // SpringApplication.class
void refresh(); // ConfigurableApplicationContext.class(这是个接口)
void refresh(); // AbstractApplicationContext.class(这是个抽象类,实现了上边接口)
//下边是上边抽象类的两个子类,但它们都没覆写refresh(),只调用了抽象类的refresh()
final void refresh() // ServletWebServerApplicationContext.class
final void refresh() // ReactiveWebServerApplicationContext.class
所以,我们只需关注于:AbstractApplicationContext#refresh()
@Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing. //容器刷新前的准备:设置上下文状态,获取属性,验证必要的属性等 prepareRefresh(); // Tell the subclass to refresh the internal bean factory. // 获取新的beanFactory,销毁原有beanFactory、为每个bean生成BeanDefinition等。 // 注意,此处是获取新的,销毁旧的,这就是刷新的意义 ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context. // 配置beanFactory:设置BeanPostProcessor、ClassLoader,SpEL表达式解析器等 // BeanPostProcessor:ApplicationContextAwareProcessor和ApplicationListenerDetector // 前者:它回调实现了ApplicationContextAware的类的setApplicationContext()方法, // 后者:将ApplicationListener的实现类bean加入到监听器列表中 prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. // 空方法,允许在子类中对beanFactory进行后置处理。 postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. // 实例化并调用所有注册的beanFactory后置处理器(实现接口BeanFactoryPostProcessor的bean)。 // 在beanFactory标准初始化之后执行 例如:PropertyPlaceholderConfigurer(处理占位符) invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. // 注册并实例化BeanPostProcessor的实现类。 // 因为里面调用了getBean()方法,所以实际也会实例化BeanPostProcessor // 例如: // AutowiredAnnotationBeanPostProcessor(处理被@Autowired注解修饰的bean并注入) // RequiredAnnotationBeanPostProcessor(处理被@Required注解修饰的方法) // CommonAnnotationBeanPostProcessor(处理@PreDestroy、@PostConstruct、@Resource等多个注解的作用)等。 // 自定义的BeabPostProcessor registerBeanPostProcessors(beanFactory); // Initialize message source for this context. // 初始化国际化工具类MessageSource initMessageSource(); // Initialize event multicaster for this context. // 初始化事件广播器 initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. // 模板方法,在容器刷新的时候可以自定义逻辑(子类自己去实现逻辑),不同的Spring容器做不同的事情 onRefresh(); // Check for listener beans and register them. // 注册监听器,并且广播early application events,也就是早期的事件 registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. // 实例化所有剩余的(非懒加载)单例Bean(我们自定义的Bean)。此时各种BeanPostProcessor起作用。 // 比如invokeBeanFactoryPostProcessors方法中根据各种注解解析出来的类,在这时被初始化 // 为什么说是剩余呢?若开发人员自定义了BeanPostProcessor,它在前面已实例化,所以这里不会再实例化 finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. // refresh做完之后需要做的其他事情 // 清除上下文资源缓存(如扫描中的ASM元数据) // 初始化上下文的生命周期处理器,并刷新(找出Lifecycle接口的实现类(bean)并执行其onRefresh()方法。 // 发布ContextRefreshedEvent事件告知对应的ApplicationListener进行相应操作 finishRefresh(); } catch (BeansException ex) { if (logger.isWarnEnabled()) { logger.warn("Exception encountered during context initialization - " + "cancelling refresh attempt: " + ex); } // Destroy already created singletons to avoid dangling resources. //如果刷新失败那么就会将已经创建好的单例Bean销毁掉 destroyBeans(); // Reset 'active' flag. //重置context的活动状态 告知是失败的 cancelRefresh(ex); // Propagate exception to caller. //抛出异常 throw ex; } finally { // Reset common introspection caches in Spring's core, since we // might not ever need metadata for singleton beans anymore... // 失败与否,都会重置Spring内核的缓存。因为可能不再需要metadata给单例Bean了。 resetCommonCaches(); } } }
refresh()详述
AbstractApplicationContext#refresh()
在refresh()方法中,比较重要的方法为invokeBeanFactoryPostProcessors(beanFactory) 和 finishBeanFactoryInitialization(beanFactory)。其他方法都比较简单。
prepareRefresh()
概述
容器刷新前的准备:设置上下文状态,获取属性,验证必要的属性等
位于:AbstractApplicationContext类
protected void prepareRefresh() { //记录容器启动时间,然后设立对应的标志位 this.startupDate = System.currentTimeMillis(); this.closed.set(false); this.active.set(true); // 打印info日志:开始刷新this此容器了 if (logger.isInfoEnabled()) { logger.info("Refreshing " + this); } // Initialize any placeholder property sources in the context environment // 这是扩展方法,由子类去实现,可以在验证之前为系统属性设置一些值可以在子类中实现此方法 // 因为我们这边是AnnotationConfigApplicationContext,可以看到不管父类还是自己,都什么都没做,所以此处先忽略 initPropertySources(); // Validate that all properties marked as required are resolvable // see ConfigurablePropertyResolver#setRequiredProperties //这里有两步,getEnvironment(),然后是是验证是否系统环境中有RequiredProperties参数值 如下详情 // 然后管理Environment#validateRequiredProperties 后面在讲到环境的时候再专门讲解吧 // 这里其实就干了一件事,验证是否存在需要的属性 getEnvironment().validateRequiredProperties(); // Allow for the collection of early ApplicationEvents, // to be published once the multicaster is available... // 初始化容器,用于装载早期的一些事件 this.earlyApplicationEvents = new LinkedHashSet<>(); }
AbstractApplicationContext#getEnvironment()
getEnvironment()的顶层接口位于:EnvironmentCapable,有如下实现
注意ConfigurableApplicationContext是接口,所以其实容器的实现只有AbstractApplicationContext
AbstractApplicationContext:上下文
ConfigurableApplicationContext:容器上下文
GenericFilterBean:Spring的过滤器
HttpServletBean:DispatcherServlet
obtainFreshBeanFactory()
概述
重新创建一个bean工厂,并销毁原工厂。主要工作是创建DefaultListableBeanFactory实例,解析配置文件,注册Bean的定义信息。
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { refreshBeanFactory(); ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (logger.isDebugEnabled()) { logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory); } return beanFactory; }
refreshBeanFactory()是具体的刷新BeanFactory。即:AbstractRefreshableApplicationContext#refreshBeanFactory
@Override protected final void refreshBeanFactory() throws BeansException { // 判断是否已经存在BeanFactory,存在则销毁所有Beans,并且关闭BeanFactory // 避免重复加载BeanFactory if (hasBeanFactory()) { destroyBeans(); closeBeanFactory(); } try { // 创建具体的beanFactory,这里创建的是DefaultListableBeanFactory,最重要的beanFactory spring注册及加载bean就靠它 // createBeanFactory()这个方法,看下面,还有得说的 DefaultListableBeanFactory beanFactory = createBeanFactory(); beanFactory.setSerializationId(getId()); // 这句比较简单,就是把当前旧容器的一些配置值复制给新容器 // allowBeanDefinitionOverriding属性是指是否允对一个名字相同但definition不同进行重新注册,默认是true。 // allowCircularReferences属性是指是否允许Bean之间循环引用,默认是true. // 这两个属性值初始值为空:复写此方法即可customizeBeanFactory customizeBeanFactory(beanFactory); // 这个就是最重要的了,加载所有的Bean配置信息,具体如下详细解释 // 它属于模版方法,由子类去实现加载的方式 loadBeanDefinitions(beanFactory); synchronized (this.beanFactoryMonitor) { this.beanFactory = beanFactory; } } catch (IOException ex) { throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex); } }
createBeanFactory()
// 创建的时候就是new了一个工厂:DefaultListableBeanFactory 这个时候工厂里面所有东西都是默认值,很多还没有完成初始化属性的设置呢 protected DefaultListableBeanFactory createBeanFactory() { return new DefaultListableBeanFactory(getInternalParentBeanFactory()); } // 给设置父的BeanFactory,若存在的话 public AbstractAutowireCapableBeanFactory(@Nullable BeanFactory parentBeanFactory) { this(); setParentBeanFactory(parentBeanFactory); } // 父类空构造器有这么些语句 public AbstractAutowireCapableBeanFactory() { super(); // 这里是重点。忽略自动装配。这里指定的都是接口。什么意思呢? // ignoreDependencyInterface的真正意思是在自动装配时忽略指定接口的实现类中,对外的依赖。(这里面注意:@Autowired和它的关系,其实是有坑的,后续会专门讲解这个坑) ignoreDependencyInterface(BeanNameAware.class); ignoreDependencyInterface(BeanFactoryAware.class); ignoreDependencyInterface(BeanClassLoaderAware.class); } //找到父的,若存在就返回 若存在父容器就存在父的BeanFactory @Nullable protected BeanFactory getInternalParentBeanFactory() { return (getParent() instanceof ConfigurableApplicationContext) ? ((ConfigurableApplicationContext) getParent()).getBeanFactory() : getParent(); }
AnnotationConfigWebApplicationContext#loadBeanDefinitions()方法,加载Bean的定义
@Override protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) { // 初始化这个脚手架 其实就是直接new出实例。具体做的工作,下面有相关博文链接 AnnotatedBeanDefinitionReader reader = getAnnotatedBeanDefinitionReader(beanFactory); ClassPathBeanDefinitionScanner scanner = getClassPathBeanDefinitionScanner(beanFactory); // 生成Bean的名称的生成器,如果自己没有setBeanNameGenerator(可以自定义),这里目前为null BeanNameGenerator beanNameGenerator = getBeanNameGenerator(); if (beanNameGenerator != null) { reader.setBeanNameGenerator(beanNameGenerator); scanner.setBeanNameGenerator(beanNameGenerator); //若我们注册了beanName生成器,那么就会注册进容器里面 beanFactory.registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, beanNameGenerator); } //这是给reader和scanner注册scope的解析器 此处为null ScopeMetadataResolver scopeMetadataResolver = getScopeMetadataResolver(); if (scopeMetadataResolver != null) { reader.setScopeMetadataResolver(scopeMetadataResolver); scanner.setScopeMetadataResolver(scopeMetadataResolver); } // 此处注意了:annotatedClasses和basePackages一般是选其一(当然看到此处,他们是可以并存的) //我们可以自己指定annotatedClasses 配置文件,同时也可以交给下面扫描 if (!this.annotatedClasses.isEmpty()) { // 这里会把所有的配置文件输出=======info日志 请注意观察控制台 if (logger.isInfoEnabled()) { logger.info("Registering annotated classes: [" + StringUtils.collectionToCommaDelimitedString(this.annotatedClasses) + "]"); } // 若是指明的Bean,就交给reader去处理,至于怎么处理,见上篇博文的doRegisterBean去怎么解析每一个Config Bean的 reader.register(ClassUtils.toClassArray(this.annotatedClasses)); } // 也可以是包扫描的方式,扫描配置文件的Bean if (!this.basePackages.isEmpty()) { // 输出对应的info日志 if (logger.isInfoEnabled()) { logger.info("Scanning base packages: [" + StringUtils.collectionToCommaDelimitedString(this.basePackages) + "]"); } // 这里重要了,scan方法具体做了什么事,上篇博文也有详细的介绍,请参阅 scanner.scan(StringUtils.toStringArray(this.basePackages)); } // 此处的意思是,也可以以全类名的形式注册。比如可以调用setConfigLocations设置(这在xml配置中使用较多) 可以是全类名,也可以是包路径 String[] configLocations = getConfigLocations(); if (configLocations != null) { for (String configLocation : configLocations) { try { Class<?> clazz = ClassUtils.forName(configLocation, getClassLoader()); reader.register(clazz); } catch (ClassNotFoundException ex) { // 发现不是全类名,那就当作包扫描吧 int count = scanner.scan(configLocation); } } } }
postProcessBeanFactory(beanFactory)
空方法,允许在子类中对beanFactory进行后置处理。
invokeBeanFactoryPostProcessors(beanFactory)
概述
该方法的作用是执行所有的BeanFactoryPostProcessor,由于Spring会内置一个BeanFactoryPostProcessor,即ConfigurationClassPostProcessor(如果开发人员不自定义,默认情况下只有这一个BeanFactoryPostProcessor),这个后置处理器在处理时,会解析出所有交由Spring容器管理的Bean,将它们解析成BeanDefinition,然后放入到BeanFactory的BeanDefinitionMap中。
该方法最终会调用到PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors()方法,主要作用是执行所有BeanFactoryPostProcessor的postProcessorBeanFactory()方法。BeanFactoryPostProcessor又分为两种情况,一种是直接实现BeanFactoryPostProcessor接口的类,另一种情况是实现了BeanDefinitionRegistryPostProcessor接口(BeanDefinitionRegistryPostProcessor继承了BeanFactoryPostProcessor接口)。
在执行过程中先执行所有的BeanDefinitionRegistryPostProcessor的postProcessorBeanDefinitionRegistry()方法,然后再执行BeanFacotryPostProcessor的postProcessorBeanFactory()方法。
默认情况下,Spring有一个内置的BeanFactoryPostProcessor,即:ConfigurationClassPostProcessor类,该类实现了BeanDefinitionRegistryPostProcessor类,所以会执行ConfigurationClassPostProcessor.postProcessorBeanDefinitionRegistry,ConfigurationClassPostProcessor的UML图如上(删减了部分不重要的继承关系)
registerBeanPostProcessors(beanFactory)
另见:Spring–BeanPostProcessor–作用/介绍 – 自学精灵
概述
该方法的作用是找到所有的BeanPostProcessor,然后将这些BeanPostProcessor实例化(会调用getBean()方法,getBean()方法的主要逻辑是,如果bean存在于BeanFactory中,则返回bean;如果不存在,则会去创建。在后面会仔细分析getBean()的执行逻辑)。将这些PostProcessor实例化后,最后放入到BeanFactory的beanPostProcessors属性中。
问题:如何找到所有的BeanPostProcessor? 包括Spring内置的和开发人员自定义的。
由于在refresh()方法中,会先执行完invokeBeanFactoryPostProcessor()方法,这样所有自定义的BeanPostProcessor类均已经被扫描出并解析成BeanDefinition(扫描和解析又是谁做的呢?ConfigurationClassPostProcessor做的),存入至BeanFactory的BeanDefinitionMap,所以这儿能通过方法如下一行代码找出所有的BeanPostProcessor,然后通过getBean()全部实例化,最后再将实例化后的对象加入到BeanFactory的beanPostProcessors属性中,该属性是一个List集合。
最后再重新注册了ApplicationListenerDetector,这样做的目的是为了将ApplicationListenerDetector放入到后置处理器的最末端
registerBeanPostProcessor() 最终调用的是PostProcessorRegistrationDelegate.registerBeanPostProcessors(),下面是PostProcessorRegistrationDelegate.registerBeanPostProcessors()方法的代码。
BeanPostProcessor存在优先级,实现了PriorityOrdered接口的优先级最高,其次是Ordered接口,最后是普通的BeanPostProcessor。优先级最高的,会最先放入到beanPostProcessors这个集合的最前面,这样在执行时,会最先执行优先级最高的后置处理器(因为List集合是有序的)。这样在实际应用中,如果我们碰到需要优先让某个BeanPostProcessor执行,则可以让其实现PriorityOrdered接口或者Ordered接口。
initMessageSource()
用来支持消息国际化,现在一般项目中不会用到国际化相关的知识。
initApplicationEventMulticaster()
概述
该方法初始化了一个事件广播器,如果容器中存在了beanName为applicationEventMulticaster的广播器,则使用该广播器;如果没有,则初始化一个SimpleApplicationEventMulticaster。该事件广播器是用来做应用事件分发的,这个类会持有所有的事件监听器(ApplicationListener),当有ApplicationEvent事件发布时,该事件监听器能根据事件类型,检索到对该事件感兴趣的ApplicationListener。
源码
protected void initApplicationEventMulticaster() { ConfigurableListableBeanFactory beanFactory = getBeanFactory(); // 判断spring容器中是否已经存在beanName = applicationEventMulticaster的事件广播器 // 例如:如果开发人员自己注册了一个 // 如果存在,则使用已经存在的;否则使用spring默认的:SimpleApplicationEventMulticaster if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) { this.applicationEventMulticaster = beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class); } else { this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory); beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster); } }
onRefresh()
概述
执行其他的初始化操作,例如和SpringMVC整合时,需要初始化一些其他的bean。对于纯Spring工程来说,onRefresh()方法是一个空方法。
如果我们整合了SpringMVC,它会启动一个TomcatServer这个服务器。
源码
如果我们整合了SpringMVC,则其其最终覆写方法为:ServletWebServerApplicationContext#onRefresh()
protected void onRefresh() { super.onRefresh(); try { this.createWebServer(); } catch (Throwable var2) { throw new ApplicationContextException("Unable to start web server", var2); } }
private void createWebServer() { WebServer webServer = this.webServer; ServletContext servletContext = this.getServletContext(); if (webServer == null && servletContext == null) { ServletWebServerFactory factory = this.getWebServerFactory(); this.webServer = factory.getWebServer(new ServletContextInitializer[]{this.getSelfInitializer()}); this.getBeanFactory().registerSingleton("webServerGracefulShutdown", new WebServerGracefulShutdownLifecycle(this.webServer)); this.getBeanFactory().registerSingleton("webServerStartStop", new WebServerStartStopLifecycle(this, this.webServer)); } else if (servletContext != null) { try { this.getSelfInitializer().onStartup(servletContext); } catch (ServletException var4) { throw new ApplicationContextException("Cannot initialize servlet context", var4); } } this.initPropertySources(); }
registerListeners()
概述
将自定义的listener的bean名称放入到事件广播器中,同时还会将早期的ApplicationEvent发布(对于单独的Spring工程来说,在此时不会有任何ApplicationEvent发布,但是和SpringMVC整合时,SpringMVC会执行onRefresh()方法,在这里会发布事件)。
源码
protected void registerListeners() { // Register statically specified listeners first. for (ApplicationListener<?> listener : getApplicationListeners()) { getApplicationEventMulticaster().addApplicationListener(listener); } // 从BeanFactory中找到所有ApplicationListener,但不初始化,因为要在后面bean实例化的过程中,让所有的BeanPostProcessor去改造它们 String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false); for (String listenerBeanName : listenerBeanNames) { // 将事件监听器的beanName放入到事件广播器中 getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName); } // 发布早期的事件(纯的spring工程,在此时一个事件都没有) Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents; this.earlyApplicationEvents = null; if (earlyEventsToProcess != null) { for (ApplicationEvent earlyEvent : earlyEventsToProcess) { getApplicationEventMulticaster().multicastEvent(earlyEvent); } } }
finishBeanFactoryInitialization(beanFactory)
概述
该方法十分重要,它完成了所有非懒加载的单例Bean的实例化和初始化,属性的填充以及解决了循环依赖等问题。
详述
见: Spring-Bean的创建过程/获取流程 – 自学精灵
finishRefresh()
概述
- 清除上下文资源缓存(如扫描中的ASM元数据)
- 初始化上下文的生命周期处理器,并刷新(找出Lifecycle接口的实现类(bean)并执行其onRefresh()方法。
- 发布ContextRefreshedEvent事件告知对应的ApplicationListener进行相应操作
代码
protected void finishRefresh() { this.clearResourceCaches(); this.initLifecycleProcessor(); this.getLifecycleProcessor().onRefresh(); this.publishEvent((ApplicationEvent)(new ContextRefreshedEvent(this))); LiveBeansView.registerApplicationContext(this); }
resetCommonCaches()
概述
在前面创建bean时,对单例bean的元数据信息进行了缓存,而单例bean在容器启动后,不会再进行创建了,因此这些缓存的信息已经没有任何用处了,在这里进行清空,释放部分内存。
代码
protected void resetCommonCaches() { ReflectionUtils.clearCache(); AnnotationUtils.clearCache(); ResolvableType.clearCache(); CachedIntrospectionResults.clearClassLoader(this.getClassLoader()); }
请先
!