在Springboot下容器启动的处理方法分析:
下个这个方法就是启动调用的方法了,下面分析下
第一个方法:
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
ArrayList exceptionReporters = new ArrayList();
this.configureHeadlessProperty();
//获取SpringApplicationRunListener实例,#getRunListeners方法根据SpringApplicationRunListener接口类型去加载其在springboot jar包下的spring.factories配置的实现类。有且只有一个EventPublishingRunListener实现。该类初始化一个spring事件传播管理器 SimpleApplicationEventMulticaster,后续实现 ApplicationEvent接口的事件类型均由该类去处理。
SpringApplicationRunListeners listeners = this.getRunListeners(args);
//发布一个ApplicationStartingEvent事件
listeners.starting();
Collection exceptionReporters1;
try {
//获取命令行启动参数,并作为IOC容器的环境变量初始化进去
DefaultApplicationArguments ex = new DefaultApplicationArguments(args);
//创建environment,装配PropertySources ,values:
“defaultProperties”,"springApplicationCommandLineArgs",配置activeProfiles。发布ApplicationEnvironmentPreparedEvent 事件(可以通过实现该事件监听来修改IOC环境变量,在启动阶段),
最后将处理化好的environment 关联至 ”configurationProperties“ 属性上。
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, ex);
this.configureIgnoreBeanInfo(environment);
//可以配置启动时日志打印的banner
Banner printedBanner = this.printBanner(environment);
//根据webApplicationType 类型来创建,一般web容器使用的 AnnotationConfigServletWebServerApplicationContext,默认 AnnotationConfigApplicationContext,reactive 峰哥使用 AnnotationConfigReactiveWebServerApplicationContext,目前我们主要使用的是 第一种。
//AnnotationConfigApplicationContext类的构造时会调用refresh方法,该方法会构造IOC的核心。可转至下面refresh方法分析。
context = this.createApplicationContext();
exceptionReporters1 = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, new Object[]{context});
//这个可以用于springboot 特有的功能,比如上面的事件SpringApplicationRunListener接口可以拓展这个接口的实现方法contextPrepared 方法的调用用于applicationContext 的处理。以及特有的Bean实例的注册。
this.prepareContext(context, environment, listeners, ex, printedBanner);
this.refreshContext(context);
this.afterRefresh(context, ex);
stopWatch.stop();
if(this.logStartupInfo) {
(new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
}
listeners.started(context);
this.callRunners(context, ex);
} catch (Throwable var10) {
this.handleRunFailure(context, var10, exceptionReporters, listeners);
throw new IllegalStateException(var10);
}
try {
listeners.running(context);
return context;
} catch (Throwable var9) {
this.handleRunFailure(context, var9, exceptionReporters1, (SpringApplicationRunListeners)null);
throw new IllegalStateException(var9);
}
}
第二个方法:
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
//如果是servlet 容器,需要将servletConfig 加载进 environment
//初始化 earlyApplicationEvents 可以尽早执行的事件,等到 事件传播器一旦可以使用就去执行。
// Prepare this context for refreshing.
prepareRefresh();
//构建beanFactory,可以发现实际上 new DefaultListableBeanFactory。可以配置beanFactory 是否支持 allowBeanDefinitionOverriding,allowCircularReferences(单例bean之间是可以相互引用的)。然后进行beanDefine 的加载。这其中就不得不提到 ClassPathBeanDefinitionScanner ,这个类主要干的是就是将 @Component注解、@ManagedBean、@Name 标注的类信息扫描进registry 中。
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// 在这过程中实在配置上面beanFactory,包括aware接口类型应该在后续autoaware时被忽略注入,以及BeanFactory、ResourceLoader、ApplicationEventPublisher、ApplicationContext这类接口实现类应该在后续辅助解析依赖时得到应用。其中有两个beanPostProcess 实现类被加入beanFactory的beanPostProcessors列表中
ApplicationContextAwareProcessor 类的作用是对 实现了aware接口的bean 的对应属性的赋值。
ApplicationListenerDetector 类的作用是在Bean 在初始化后来判断当前bean 是够是一个事件监听单例bean是就会把当前bean 加在事件传播器中。
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
//运行其子类自己特有的beanPostProcess 添加进去来完成beanPostProcess列表的完善。
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
//调用 BeanFactoryPostProcessor 接口实现类,如果为
BeanDefinitionRegistryPostProcessor接口实现类,则说明该类还会做一些beanDefinition 的解析工作。其他的实现类被区分为 常规的beanFactoryPostProcess 实现类。按照优先级先后执行BeanDefinitionRegistryPostProcessor实现类的方法。最后再按照优先级再去执行常规的beanProcess 。实现优先级的排序可参考实现 PriorityOrdered.class 或者 Order.class接口。
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
//这里是注册BeanPostProcess 接口实现类,也是按照优先级前后,再按照如果是 MergedBeanDefinitionPostProcessor 要优先于常规类先去处理,
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
//初始化事件传播器,spring-boot是在一开始就初始化了
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
//一个是将已经初始化好的listener Bean 加入传播器列表,二是将 listener bean的全部beanName 加入列表,这个地方是说 factoryBeans 还未初始化,三是将earlyApplicationEvents中的事件去执行。
// Check for listener beans and register them.
registerListeners();
//再去完善一下beanFactory 的属性:PropertyPlaceholderConfigurer的EmbeddedValueResolver,值解析器,最后出发非延迟加载Bean 的初始化。
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
//发布 ContextRefreshedEvent事件,并将bean注册进Mbean 管理。
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.
destroyBeans();
// Reset 'active' flag.
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...
resetCommonCaches();
}
}
}
第三部分:
关于Factorybean 的初始化,实现factorybean 接口的bean 会被spring先初始化,其beanName 为$beanName,
其getObject() 返回的beanName 的bean 会根据适配条件去看是否会同步被初始化。如果是 实现的 SmartFactoryBean 接口的bean 并且其isEagerInit 方法被覆写成 true,怎会同步被初始化。
第四部分:doGetBean 的方法 也就是 bean 的初始化过程
这部分方法叙述一下,在调用 createBean 方法时, 的实现类会被调用,再到执行 doCreateBean 方法,其中的 populateBean 方法可以在初始化化bean 前给一次修改bean field 的机会如果存在 InstantiationAwareBeanPostProcessor 接口的实现类。再执行initializeBean方法,先执行
BeanNameAware-》BeanClassLoaderAware-》BeanFactoryAware 属性的设值。再去执行 beanProcessor#postProcessBeforeInitializatio所有方法。再去执行 InitializingBean 的初始化方法。最后执行
beanProcessor#postProcessAfterInitialization来完成bean 初始化。
总结一下,spring框架中很多地方都是使用beanProcessor 接口来干预 bean 的生成。这是因为单例bean 在生成的过程中少不了执行其中的方法。
第五部分关于几个注解的处理逻辑位置:
@AutoAware @Value @Inject->AutowiredAnnotationBeanPostProcessor
@PostConstruct @PreDestroy-》CommonAnnotationBeanPostProcessor