SpringBoot配置外部Tomcat项目启动流程源码分析(二)
SpringBoot应用默认以Jar包方式并且使用内置Servlet容器(默认Tomcat),该种方式虽然简单但是默认不支持JSP并且优化容器比较复杂。故而我们可以使用习惯的外置Tomcat方式并将项目打War包。
【6】SpringApplication.run方法详细分析-准备环境③ prepareEnvironment–环境构建
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
跟进去该方法:
private ConfigurableEnvironment prepareEnvironment(
SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments) {
// Create and configure the environment
//获取对应的ConfigurableEnvironment
ConfigurableEnvironment environment = getOrCreateEnvironment();
//配置
configureEnvironment(environment, applicationArguments.getSourceArgs());
//发布环境已准备事件,这是第二次发布事件
listeners.environmentPrepared(environment);
bindToSpringApplication(environment);
if (this.webApplicationType == WebApplicationType.NONE) {
environment = new EnvironmentConverter(getClassLoader())
.convertToStandardEnvironmentIfNecessary(environment);
}
ConfigurationPropertySources.attach(environment);
return environment;
}
来看一下getOrCreateEnvironment()方法,前面已经提到,environment已经被设置了servlet类型,所以这里创建的是环境对象是StandardServletEnvironment。
private ConfigurableEnvironment getOrCreateEnvironment() {
if (this.environment != null) {
return this.environment;
}
if (this.webApplicationType == WebApplicationType.SERVLET) {
return new StandardServletEnvironment();
}
return new StandardEnvironment();
}
枚举类WebApplicationType是SpringBoot2新增的特性,主要针对spring5引入的reactive特性。
枚举类型如下:
public enum WebApplicationType {
//不需要再web容器的环境下运行,普通项目
NONE,
//基于servlet的web项目
SERVLET,
//这个是spring5版本开始的新特性
REACTIVE
}
Environment接口提供了4种实现方式,StandardEnvironment、StandardServletEnvironment和MockEnvironment、StandardReactiveWebEnvironment,分别代表普通程序、Web程序、测试程序的环境、响应式web环境,
配置环境代码如下:
protected void configureEnvironment(ConfigurableEnvironment environment,
String[] args) {
configurePropertySources(environment, args);
configureProfiles(environment, args);
}
在返回return new StandardServletEnvironment();对象的时候,会完成一系列初始化动作,主要就是将运行机器的系统变量和环境变量,加入到其父类AbstractEnvironment定义的对象MutablePropertySources中,MutablePropertySources对象中定义了一个属性集合:
private final List<PropertySource<?>> propertySourceList;
public MutablePropertySources() {
this.propertySourceList = new CopyOnWriteArrayList();
this.logger = LogFactory.getLog(this.getClass());
}
执行到这里,系统变量和环境变量已经被载入到配置文件的集合中,接下来就行解析项目中的配置文件。
关于CopyOnWriteArrayList可以参考博文浅谈从fail-fast机制到CopyOnWriteArrayList使用
**④ listeners.environmentPrepared(environment);–第二次发布事件**
来看一下listeners.environmentPrepared(environment);,上面已经提到了,这里是第二次发布事件。什么事件呢?顾名思义,系统环境初始化完成的事件。
**跟进方法:**
**继续跟:**
@Override
public void environmentPrepared(ConfigurableEnvironment environment) {
this.initialMulticaster.multicastEvent(new ApplicationEnvironmentPreparedEvent(
this.application, this.args, environment));
}
**这里将要广播ApplicationEnvironmentPreparedEvent事件了**
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
Executor executor = getTaskExecutor();
if (executor != null) {
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
}
}
发布事件的流程上面已经讲过了,这里不在赘述。来看一下根据事件类型获取到的监听器:
**遍历监听器,调用不同监听器对该事件的处理。**
可以看到获取到的监听器和第一次发布启动事件获取的监听器有几个是重复的,这也验证了监听器是可以多次获取,根据事件类型来区分具体处理逻辑。上面介绍日志监听器的时候已经提到。
主要来看一下ConfigFileApplicationListener,该监听器非常核心,主要用来处理项目配置。项目中的 properties 和yml文件都是其内部类所加载。
**首先方法执行入口:**
**调用onApplicationEnvironmentPreparedEvent方法:**
private void onApplicationEnvironmentPreparedEvent(
ApplicationEnvironmentPreparedEvent event) {
List<EnvironmentPostProcessor> postProcessors = loadPostProcessors();
postProcessors.add(this);
AnnotationAwareOrderComparator.sort(postProcessors);
for (EnvironmentPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessEnvironment(event.getEnvironment(),
event.getSpringApplication());
}
首先还是会去读spring.factories 文件,List<EnvironmentPostProcessor> postProcessors = loadPostProcessors();获取的处理类有以下四种:
SystemEnvironmentPropertySourceEnvironmentPostProcessor(加载系统环境变量):
SpringApplicationJsonEnvironmentPostProcessor:
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment,
SpringApplication application) {
MutablePropertySources propertySources = environment.getPropertySources();
StreamSupport.stream(propertySources.spliterator(), false)
.map(JsonPropertyValue::get).filter(Objects::nonNull).findFirst()
.ifPresent((v) -> processJson(environment, v));
}
在执行完上述三个监听器流程后,ConfigFileApplicationListener会执行该类本身的逻辑。由其内部类Loader加载项目制定路径下的配置文件:
// Note the order is from least to most specific (last one wins)
private static final String DEFAULT\_SEARCH\_LOCATIONS =
"classpath:/,classpath:/config/,file:./,file:./config/";
ConfigFileApplicationListener
@Override
public void postProcessEnvironment(ConfigurableEnvironment environment,
SpringApplication application) {
addPropertySources(environment, application.getResourceLoader());
}
**内部类Loader构造函数:**
Loader(ConfigurableEnvironment environment, ResourceLoader resourceLoader) {
this.environment = environment;
this.resourceLoader = (resourceLoader != null ? resourceLoader
: new DefaultResourceLoader());
this.propertySourceLoaders = SpringFactoriesLoader.loadFactories(
PropertySourceLoader.class, getClass().getClassLoader());
}
**其获取的propertySourceLoaders 如下:**
至此使用ConfigFileApplicationListener将应用配置文件加载进来,接下来该其它六个监听器依次处理。
监听器处理完毕返回到ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments)处,此时environment对象如下:
**接下来将environment绑定到SpringApplication上。**
返回到SpringApplication类中ConfigurableApplicationContext run(String... args)方法处:
【7】SpringApplication.run方法详细分析-创建容器**⑤ createApplicationContext();创建容器**
在SpringBootServletInitializer.createRootApplicationContext(ServletContext servletContext)中设置过contextClass:
builder.contextClass(AnnotationConfigServletWebServerApplicationContext.class);
**看创建容器的代码:**
protected ConfigurableApplicationContext createApplicationContext() {
Class<?> contextClass = this.applicationContextClass;
//如果contextClass 为null,就根据webApplicationType加载对应class;
//这里不为null,是AnnotationConfigServletWebServerApplicationContext
if (contextClass == null) {
try {
switch (this.webApplicationType) {
case SERVLET:
contextClass = Class.forName(DEFAULT\_WEB\_CONTEXT\_CLASS);
break;
case REACTIVE:
contextClass = Class.forName(DEFAULT\_REACTIVE\_WEB\_CONTEXT\_CLASS);
break;
default:
contextClass = Class.forName(DEFAULT\_CONTEXT\_CLASS);
}
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Unable create a default ApplicationContext, "
+ "please specify an ApplicationContextClass",
ex);
}
}
//这里根据反射实例化容器
return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}
**创建的context如下:**
**⑥ 报告错误信息**
这里还是以同样的方式获取 spring.factories文件中的指定类:
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type,
Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
// Use names and ensure unique to protect against duplicates
Set<String> names = new LinkedHashSet<>(
SpringFactoriesLoader.loadFactoryNames(type, classLoader));
List<T> instances = createSpringFactoriesInstances(type, parameterTypes,
classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
**如果应用启动失败,则会打印失败信息:**
@Override
public void report(FailureAnalysis failureAnalysis) {
if (logger.isDebugEnabled()) {
logger.debug("Application failed to start due to an exception",
failureAnalysis.getCause());
}
if (logger.isErrorEnabled()) {
logger.error(buildMessage(failureAnalysis));
}
}
【8】SpringApplication.run方法详细分析-容器刷新之前准备
**⑦ prepareContext–准备容器**
这一步主要是在容器刷新之前的准备动作。包含一个非常关键的操作:将启动类注入容器,为后续开启自动化配置奠定基础。
private void prepareContext(ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
//设置容器环境,包括各种变量
context.setEnvironment(environment);
//执行容器后置处理
postProcessApplicationContext(context);
//执行容器中的ApplicationContextInitializer(包括 spring.factories和自定义的实例)
applyInitializers(context);
//发送容器已经准备好的事件,通知各监听器
listeners.contextPrepared(context);
//打印log
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
// Add boot specific singleton beans
//注册启动参数bean,这里将容器指定的参数封装成bean,注入容器
context.getBeanFactory().registerSingleton("springApplicationArguments",
applicationArguments);
//设置banner
if (printedBanner != null) {
context.getBeanFactory().registerSingleton("springBootBanner", printedBanner);
}
// Load the sources
//获取我们的启动类指定的参数,可以是多个
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
//加载我们的启动类,将启动类注入容器
load(context, sources.toArray(new Object[0]));
//发布容器已加载事件。
listeners.contextLoaded(context);
}
**容器的后置处理:**
protected void postProcessApplicationContext(ConfigurableApplicationContext context) {
if (this.beanNameGenerator != null) {
context.getBeanFactory().registerSingleton(
AnnotationConfigUtils.CONFIGURATION\_BEAN\_NAME\_GENERATOR,
this.beanNameGenerator);
}
if (this.resourceLoader != null) {
if (context instanceof GenericApplicationContext) {
((GenericApplicationContext) context)
.setResourceLoader(this.resourceLoader);
}
if (context instanceof DefaultResourceLoader) {
((DefaultResourceLoader) context)
.setClassLoader(this.resourceLoader.getClassLoader());
}
}
}
这里默认不执行任何逻辑,因为beanNameGenerator和resourceLoader默认为空。之所以这样做,是springBoot留给我们的扩展处理方式,类似于这样的扩展,spring中也有很多。
**初始化器初始化方法调用**
protected void applyInitializers(ConfigurableApplicationContext context) {
for (ApplicationContextInitializer initializer : getInitializers()) {
Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(
initializer.getClass(), ApplicationContextInitializer.class);
Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
initializer.initialize(context);
}
}
**上面提到过,有7个初始化器,这里将会依次调用initialize方法:**
ServletContextApplicationContextInitializer.initialize:
public void initialize(ConfigurableWebApplicationContext applicationContext) {
//给创建的容器设置servletContext引用
applicationContext.setServletContext(this.servletContext);
//判断true or false ,如果为true,将applicationContext放到servletContext
//这里为false。
if (this.addApplicationContextAttribute) {
this.servletContext.setAttribute(
WebApplicationContext.ROOT\_WEB\_APPLICATION\_CONTEXT\_ATTRIBUTE,
applicationContext);
}
}
ContextIdApplicationContextInitializer.initialize:
public void initialize(ConfigurableApplicationContext applicationContext) {
ContextId contextId = getContextId(applicationContext);
applicationContext.setId(contextId.getId());
applicationContext.getBeanFactory().registerSingleton(ContextId.class.getName(),
contextId);
}
为applicationContext设置ID。
listeners.contextPrepared(context)发布事件–第三次发布事件了
public void contextPrepared(ConfigurableApplicationContext context) {
for (SpringApplicationRunListener listener : this.listeners) {
listener.contextPrepared(context);
}
}
**这里listener为EventPublishingRunListener,其contextPrepared方法为空方法:**
@Override
public void contextPrepared(ConfigurableApplicationContext context) {
}
获取primarySources放到allSources
**可以看到我们的主启动类在里面。**
**加载启动指定类(重点)**
这里会将我们的启动类加载spring容器beanDefinitionMap中,为后续springBoot 自动化配置奠定基础,springBoot为我们提供的各种注解配置也与此有关。
**这里参数即为我们项目启动时传递的参数:SpringApplication.run(SpringbootwebprojectApplication.class, args);**
protected void load(ApplicationContext context, Object[] sources) {
if (logger.isDebugEnabled()) {
logger.debug(
"Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
}
//根据BeanDefinitionRegistry创建BeanDefinitionLoader
BeanDefinitionLoader loader = createBeanDefinitionLoader(
getBeanDefinitionRegistry(context), sources);
if (this.beanNameGenerator != null) {
loader.setBeanNameGenerator(this.beanNameGenerator);
}
if (this.resourceLoader != null) {
loader.setResourceLoader(this.resourceLoader);
}
if (this.environment != null) {
//设置环境
loader.setEnvironment(this.environment);
}
loader.load();
}
因为这里的applicationContext实现了BeanDefinitionRegistry接口,所以获取BeanDefinitionRegistry时将applicationContext强转返回。故而这里直接拿着applicationContext和sources获取BeanDefinitionLoader
需要注意的是,springBoot2会优先选择groovy加载方式,找不到再选用java方式。或许groovy动态加载class文件的性能更胜一筹。
private int load(Class<?> source) {
if (isGroovyPresent()
&& GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
// Any GroovyLoaders added in beans{} DSL can contribute beans here
GroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source,
GroovyBeanDefinitionSource.class);
load(loader);
}
if (isComponent(source)) {
//以注解的方式,将启动类bean信息存入beanDefinitionMap
this.annotatedReader.register(source);
return 1;
}
return 0;
}
**listeners.contextLoaded(context);广播事件容器已准备就绪–监听器第四次处理事件**
public void contextLoaded(ConfigurableApplicationContext context) {
for (SpringApplicationRunListener listener : this.listeners) {
listener.contextLoaded(context);
}
}
public void contextLoaded(ConfigurableApplicationContext context) {
for (ApplicationListener<?> listener : this.application.getListeners()) {
if (listener instanceof ApplicationContextAware) {
((ApplicationContextAware) listener).setApplicationContext(context);
}
//将application.getListeners()添加到context
context.addApplicationListener(listener);
}
//广播事件给监听器
this.initialMulticaster.multicastEvent(
new ApplicationPreparedEvent(this.application, this.args, context));
}
**此时是有四个监听器处理ApplicationPreparedEvent事件:**
ConfigFileApplicationListener.onApplicationPreparedEvent:
private void onApplicationPreparedEvent(ApplicationEvent event) {
this.logger.replayTo(ConfigFileApplicationListener.class);
addPostProcessors(((ApplicationPreparedEvent) event).getApplicationContext());
}
**addPostProcessors源码如下:**
protected void addPostProcessors(ConfigurableApplicationContext context) {
//给context中添加BeanFactoryPostProcessor
context.addBeanFactoryPostProcessor(
new PropertySourceOrderingPostProcessor(context));
}
【9】SpringApplication.run方法详细分析-刷新容器
**refreshContext(context);刷新容器,准备IOC容器的核心步骤就在这里。**
AbstractApplicationContext.refresh方法源码如下:
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
/\*\*
\* 刷新上下文环境
\* 初始化上下文环境,对系统的环境变量或者系统属性进行准备和校验
\* 如环境变量中必须设置某个值才能运行,否则不能运行,这个时候可以在这里加这个校验,
\* 重写initPropertySources方法就好了
\*/
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
/\*\*
\* 初始化BeanFactory,解析XML,相当于之前的XmlBeanFactory的操作,
\*/
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
/\*\*
\* 为上下文准备BeanFactory,即对BeanFactory的各种功能进行填充,如常用的注解@Autowired @Qualifier等
\* 设置SPEL表达式#{key}的解析器
\* 设置资源编辑注册器,如PerpertyEditorSupper的支持
\* 添加ApplicationContextAwareProcessor处理器
\* 在依赖注入忽略实现\*Aware的接口,如EnvironmentAware、ApplicationEventPublisherAware等
\* 注册依赖,如一个bean的属性中含有ApplicationEventPublisher(beanFactory),则会将beanFactory的实例注入进去
\*/
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
/\*\*
\* 提供子类覆盖的额外处理,即子类处理自定义的BeanFactoryPostProcess
\*/
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
/\*\*
\* 激活各种BeanFactory处理器,包括BeanDefinitionRegistryBeanFactoryPostProcessor和普通的BeanFactoryPostProcessor
\* 执行对应的postProcessBeanDefinitionRegistry方法 和 postProcessBeanFactory方法
\*/
invokeBeanFactoryPostProcessors(beanFactory);
/\*\*
\* 注册拦截Bean创建的Bean处理器,即注册BeanPostProcessor,不是BeanFactoryPostProcessor,注意两者的区别
\* 注意,这里仅仅是注册,并不会执行对应的方法,将在bean的实例化时执行对应的方法
\*/
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
/\*\*
\* 初始化上下文中的资源文件,如国际化文件的处理等
\*/
initMessageSource();
// Initialize event multicaster for this context.
/\*\*
\* 初始化上下文事件广播器,并放入applicatioEventMulticaster,如ApplicationEventPublisher
\*/
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
/\*\*
\* 给子类扩展初始化其他Bean
\* 在没有使用外部Tomcat项目中,还会在这里创建内置Tomcat WebServer 并启动
\*/
onRefresh();
// Check for listener beans and register them.
/\*\*
\* 在所有bean中查找listener bean,然后注册到广播器中
\*/
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
/\*\*
\* 设置转换器
\* 注册一个默认的属性值解析器
\* 冻结所有的bean定义,说明注册的bean定义将不能被修改或进一步的处理
\* 初始化剩余的非惰性的bean,即初始化非延迟加载的bean
\*/
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
/\*\*
\* 初始化生命周期处理器DefaultLifecycleProcessor,DefaultLifecycleProcessor含有start方法和stop方法,spring启动的时候调用start方法开始生命周期,
\* spring关闭的时候调用stop方法来结束生命周期,通常用来配置后台程序,启动有一直运行,如一直轮询kafka
\* 启动所有实现了Lifecycle接口的类
\* 通过spring的事件发布机制发布ContextRefreshedEvent事件,以保证对应的监听器做进一步的处理,即对那种在spring启动后需要处理的一些类,这些类实现了
\* ApplicationListener<ContextRefreshedEvent> ,这里就是要触发这些类的执行(执行onApplicationEvent方法)另外,spring的内置Event有ContextClosedEvent、ContextRefreshedEvent、ContextStartedEvent、ContextStoppedEvent、RequestHandleEvent
\* 完成初始化,通知生命周期处理器lifeCycleProcessor刷新过程,同时发出ContextRefreshEvent通知其他人
\*/
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();
}
}
}
**① obtainFreshBeanFactory();**
**默认获取的BeanFactory为DefaultListableBeanFactory,源码如下:**
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (logger.isDebugEnabled()) {
logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
**这里获取后的beanFactory如下所示:**
**②prepareBeanFactory-准备BeanFactory**
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
//设置BeanClassLoader-这里是WebappClassLoader
beanFactory.setBeanClassLoader(getClassLoader());
//设置SPEL表达式#{key}的解析器 --StandardBeanExpressionResolver
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
//设置资源编辑注册器,如PerpertyEditorSupper的支持-- ResourceEditorRegistrar
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
//添加ApplicationContextAwareProcessor处理器
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
//在依赖注入忽略实现\*Aware的接口,
//如EnvironmentAware、ApplicationEventPublisherAware等
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
注册依赖,如一个bean的属性中含有ApplicationEventPublisher(beanFactory),
//则会将beanFactory的实例注入进去
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
// Register early post-processor for detecting inner beans as ApplicationListeners.
将早期后处理器注册为应用程序监听器,以检测内部bean。
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (beanFactory.containsBean(LOAD\_TIME\_WEAVER\_BEAN\_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
// Register default environment beans.
if (!beanFactory.containsLocalBean(ENVIRONMENT\_BEAN\_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT\_BEAN\_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM\_PROPERTIES\_BEAN\_NAME)) {
beanFactory.registerSingleton(SYSTEM\_PROPERTIES\_BEAN\_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM\_ENVIRONMENT\_BEAN\_NAME)) {
beanFactory.registerSingleton(SYSTEM\_ENVIRONMENT\_BEAN\_NAME, getEnvironment().getSystemEnvironment());
}
}
**其父类ServletWebServerApplicationContext.postProcessBeanFactory如下:**
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
//添加WebApplicationContextServletContextAwareProcessor后置处理器
beanFactory.addBeanPostProcessor(
new WebApplicationContextServletContextAwareProcessor(this));
//忽略依赖接口
beanFactory.ignoreDependencyInterface(ServletContextAware.class);
}
**③ 后置处理BeanFactorypostProcessBeanFactory(beanFactory);**
@Override
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
super.postProcessBeanFactory(beanFactory);
if (this.basePackages != null && this.basePackages.length > 0) {
this.scanner.scan(this.basePackages);
}
if (!this.annotatedClasses.isEmpty()) {
this.reader.register(ClassUtils.toClassArray(this.annotatedClasses));
}
}
**注册完了,该调用BeanFactoryPostProcessors了。**
**④ invokeBeanFactoryPostProcessors(beanFactory)**
在单例实例化前调用所有注册的BeanFactoryPostProcessor:
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD\_TIME\_WEAVER\_BEAN\_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
**这里有三个BeanFactoryPostProcessor:**
ConfigurationWarningsApplicationContextInitializer.ConfigurationWarningsPostProcessor(后者是前者static
final内部类);
SharedMetadataReaderFactoryContextInitializer.CachingMetadataReaderFactoryPostProcessor(后者是前者静态内部类);
ConfigFileApplicationListener.PropertySourceOrderingPostProcessor(后者是前者内部类);
**PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors:**
class PostProcessorRegistrationDelegate {
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<>();
if (beanFactory instanceof BeanDefinitionRegistry) {
//如果beanFactory是BeanDefinitionRegistry类型,就强转一下
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new LinkedList<>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new LinkedList<>();
//遍历beanFactoryPostProcessors
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
//如果postProcessor 还是BeanDefinitionRegistryPostProcessor类型,就强转一下
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
//调用registryProcessor 的postProcessBeanDefinitionRegistry方法
registryProcessor.postProcessBeanDefinitionRegistry(registry);
//添加到registryProcessors
registryProcessors.add(registryProcessor);
}else {
//否则添加到List<BeanFactoryPostProcessor> regularPostProcessors
//也就是说只是BeanFactoryPostProcessor
regularPostProcessors.add(postProcessor);
}
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// Separate between BeanDefinitionRegistryPostProcessors that implement
// PriorityOrdered, Ordered, and the rest.
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
}
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>();
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// Finally, invoke all other BeanFactoryPostProcessors.
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
beanFactory.clearMetadataCache();
}
遍历BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors后List<BeanFactoryPostProcessor> regularPostProcessors和List<BeanDefinitionRegistryPostProcessor> registryProcessors如下所示:
**⑤ registerBeanPostProcessors(beanFactory);**
实例化并调用所有已经注册的BeanPostProcessor:
/\*\*
\* Instantiate and invoke all registered BeanPostProcessor beans,
\* respecting explicit order if given.
\* <p>Must be called before any instantiation of application beans.
\*/
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
**⑥ initMessageSource();**
初始化上下文中的资源文件,如国际化文件的处理等:
protected void initMessageSource() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(MESSAGE\_SOURCE\_BEAN\_NAME)) {
this.messageSource = beanFactory.getBean(MESSAGE\_SOURCE\_BEAN\_NAME, MessageSource.class);
// Make MessageSource aware of parent MessageSource.
if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
if (hms.getParentMessageSource() == null) {
// Only set parent context as parent MessageSource if no parent MessageSource
// registered already.
hms.setParentMessageSource(getInternalParentMessageSource());
}
}
if (logger.isTraceEnabled()) {
logger.trace("Using MessageSource [" + this.messageSource + "]");
}
}
else {
// Use empty MessageSource to be able to accept getMessage calls.
DelegatingMessageSource dms = new DelegatingMessageSource();
dms.setParentMessageSource(getInternalParentMessageSource());
this.messageSource = dms;
beanFactory.registerSingleton(MESSAGE\_SOURCE\_BEAN\_NAME, this.messageSource);
if (logger.isTraceEnabled()) {
logger.trace("No '" + MESSAGE\_SOURCE\_BEAN\_NAME + "' bean, using [" + this.messageSource + "]");
}
}
}
**⑦ initApplicationEventMulticaster**
初始化上下文事件广播器,如果不存在ApplicationEventMulticaster 则使用默认SimpleApplicationEventMulticaster。
protected void initApplicationEventMulticaster() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
if (beanFactory.containsLocalBean(APPLICATION\_EVENT\_MULTICASTER\_BEAN\_NAME)) {
this.applicationEventMulticaster =
beanFactory.getBean(APPLICATION\_EVENT\_MULTICASTER\_BEAN\_NAME, ApplicationEventMulticaster.class);
if (logger.isTraceEnabled()) {
logger.trace("Using ApplicationEventMulticaster [" + this.applicationEventMulticaster + "]");
}
}
else {
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(APPLICATION\_EVENT\_MULTICASTER\_BEAN\_NAME, this.applicationEventMulticaster);
if (logger.isTraceEnabled()) {
logger.trace("No '" + APPLICATION\_EVENT\_MULTICASTER\_BEAN\_NAME + "' bean, using " +
"[" + this.applicationEventMulticaster.getClass().getSimpleName() + "]");
}
}
}
注意,在这之前,事情发布机制都是通过SpringApplicationRunListener的实现类EventPublishingRunListener来完成的,后者内部有一个ApplicationEventMulticaster进行事件发布给ApplicationListener。在这个方法中,直接使用this.applicationEventMulticaster=赋值了一个应用事件广播器。
**⑧ onRefresh()**
ServletWebServerApplicationContext.onRefresh()方法源码如下:
protected void onRefresh() {
//调用父类onRefresh()方法
super.onRefresh();
try {
//创建WebServer
createWebServer();
}
catch (Throwable ex) {
throw new ApplicationContextException("Unable to start web server", ex);
}
}
**调用父类onRefresh()方法:**
/\*\*
\* Initialize the theme capability.
\*/
@Override
protected void onRefresh() {
this.themeSource = UiApplicationContextUtils.initThemeSource(this);
}
/\*\*
\* Initialize the ThemeSource for the given application context,
\* autodetecting a bean with the name "themeSource". If no such
\* bean is found, a default (empty) ThemeSource will be used.
\* @param context current application context
\* @return the initialized theme source (will never be {@code null})
\* @see #THEME\_SOURCE\_BEAN\_NAME
\*/
public static ThemeSource initThemeSource(ApplicationContext context) {
if (context.containsLocalBean(THEME\_SOURCE\_BEAN\_NAME)) {
ThemeSource themeSource = context.getBean(THEME\_SOURCE\_BEAN\_NAME, ThemeSource.class);
// Make ThemeSource aware of parent ThemeSource.
if (context.getParent() instanceof ThemeSource && themeSource instanceof HierarchicalThemeSource) {
HierarchicalThemeSource hts = (HierarchicalThemeSource) themeSource;
if (hts.getParentThemeSource() == null) {
// Only set parent context as parent ThemeSource if no parent ThemeSource
// registered already.
hts.setParentThemeSource((ThemeSource) context.getParent());
}
}
if (logger.isDebugEnabled()) {
logger.debug("Using ThemeSource [" + themeSource + "]");
}
return themeSource;
}
else {
// Use default ThemeSource to be able to accept getTheme calls, either
// delegating to parent context's default or to local ResourceBundleThemeSource.
HierarchicalThemeSource themeSource = null;
if (context.getParent() instanceof ThemeSource) {
themeSource = new DelegatingThemeSource();
themeSource.setParentThemeSource((ThemeSource) context.getParent());
}
else {
themeSource = new ResourceBundleThemeSource();
}
if (logger.isDebugEnabled()) {
logger.debug("Unable to locate ThemeSource with name '" + THEME\_SOURCE\_BEAN\_NAME +
"': using default [" + themeSource + "]");
}
return themeSource;
}
}
**ServletWebServerApplicationContext.createWebServer()方法如下:**
private void createWebServer() {
WebServer webServer = this.webServer;
ServletContext servletContext = getServletContext();
if (webServer == null && servletContext == null) {
ServletWebServerFactory factory = getWebServerFactory();
this.webServer = factory.getWebServer(getSelfInitializer());
}
else if (servletContext != null) {
try {
getSelfInitializer().onStartup(servletContext);
}
catch (ServletException ex) {
throw new ApplicationContextException("Cannot initialize servlet context",
ex);
}
}
initPropertySources();
}
**判断ServletContext不为null,就会调用getSelfInitializer().onStartup(servletContext);**
private org.springframework.boot.web.servlet.ServletContextInitializer getSelfInitializer() {
return this::selfInitialize;
}
private void selfInitialize(ServletContext servletContext) throws ServletException {
prepareWebApplicationContext(servletContext);
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
ExistingWebApplicationScopes existingScopes = new ExistingWebApplicationScopes(
beanFactory);
WebApplicationContextUtils.registerWebApplicationScopes(beanFactory,
getServletContext());
existingScopes.restore();
WebApplicationContextUtils.registerEnvironmentBeans(beanFactory,
getServletContext());
for (ServletContextInitializer beans : getServletContextInitializerBeans()) {
beans.onStartup(servletContext);
}
}
如下图所示,在末尾循环遍历ServletContextInitializerBean,这里有6个,分别注册了Servlet和Filter。
**⑨ registerListeners();**
添加实现了ApplicationListener 接口的bean作为监听器,并不影响其他监听器。
/\*\*
\* Add beans that implement ApplicationListener as listeners.
\* Doesn't affect other listeners, which can be added without being beans.
\*/
protected void registerListeners() {
// Register statically specified listeners first.
for (ApplicationListener<?> listener : getApplicationListeners()) {
getApplicationEventMulticaster().addApplicationListener(listener);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let post-processors apply to them!
String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
for (String listenerBeanName : listenerBeanNames) {
getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
}
// Publish early application events now that we finally have a multicaster...
Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
this.earlyApplicationEvents = null;
if (earlyEventsToProcess != null) {
for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
getApplicationEventMulticaster().multicastEvent(earlyEvent);
}
}
}
**⑩ finishBeanFactoryInitialization**
设置转换器
注册一个默认的属性值解析器
冻结所有的bean定义,说明注册的bean定义将不能被修改或进一步的处理
初始化剩余的非惰性的bean,即初始化非延迟加载的bean
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
if (beanFactory.containsBean(CONVERSION\_SERVICE\_BEAN\_NAME) &&
beanFactory.isTypeMatch(CONVERSION\_SERVICE\_BEAN\_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION\_SERVICE\_BEAN\_NAME, ConversionService.class));
}
// Register a default embedded value resolver if no bean post-processor
// (such as a PropertyPlaceholderConfigurer bean) registered any before:
// at this point, primarily for resolution in annotation attribute values.
if (!beanFactory.hasEmbeddedValueResolver()) {
beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));
}
// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.
String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String weaverAwareName : weaverAwareNames) {
getBean(weaverAwareName);
}
// Stop using the temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(null);
// Allow for caching all bean definition metadata, not expecting further changes.
beanFactory.freezeConfiguration();
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
}
**(11)finishRefresh()**
完成上下文刷新,调用LifecycleProcessor的onRefresh()方法并发布ContextRefreshedEvent事件。
/\*\*
\* Finish the refresh of this context, invoking the LifecycleProcessor's
\* onRefresh() method and publishing the
\* {@link org.springframework.context.event.ContextRefreshedEvent}.
\*/
protected void finishRefresh() {
// Clear context-level resource caches (such as ASM metadata from scanning).
clearResourceCaches();
// Initialize lifecycle processor for this context.
initLifecycleProcessor();
// Propagate refresh to lifecycle processor first.
getLifecycleProcessor().onRefresh();
// Publish the final event.
publishEvent(new ContextRefreshedEvent(this));
// Participate in LiveBeansView MBean, if active.
LiveBeansView.registerApplicationContext(this);
}
版权声明
本文仅代表作者观点,不代表博信信息网立场。