spring ApplicationContext启动过程
Posted ac_dao_di
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring ApplicationContext启动过程相关的知识,希望对你有一定的参考价值。
1. 前言
spring boot 2.1.7启动过程源码解析讲到了SpringBoot的启动过程,在第5模块和第6模块,讲到了Spring ApplicationContext的启动过程,会创建一个AnnotationConfigServletWebServerApplicationContext
,之后调用相关的ApplicationContextInitializer对其进行初始化,包括设置parent context、加载远程property构建environment等,之后注册main方法所在类,作为启动配置的第一个类,进而加载所有的业务bean。本文对第5模块和第6模块,进行更加详细的剖析。
本文源码见:源码
一张图总结spring ApplicationContext启动过程整个启动过程
2. 注册基本的注解后处理器
在SpringApplication.prepareContext方法中,会构建一个BeanDefinitionLoader,该类的构造方法在初始化的过程中,会注入常见的注解后处理器。由于AnnotationConfigServletWebServerApplicationContext继承自GenericApplicationContext,在构造函数初始化时,就已经构建了beanFactory,且类型为DefaultListableBeanFactory。所以可以添加后处理器和注册bean
BeanDefinitionLoader(BeanDefinitionRegistry registry, Object... sources)
Assert.notNull(registry, "Registry must not be null");
Assert.notEmpty(sources, "Sources must not be empty");
this.sources = sources;
// 构建AnnotatedBeanDefinitionReader
this.annotatedReader = new AnnotatedBeanDefinitionReader(registry);
this.xmlReader = (XML_ENABLED ? new XmlBeanDefinitionReader(registry) : null);
this.groovyReader = (isGroovyPresent() ? new GroovyBeanDefinitionReader(registry) : null);
this.scanner = new ClassPathBeanDefinitionScanner(registry);
this.scanner.addExcludeFilter(new ClassExcludeFilter(sources));
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment)
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
Assert.notNull(environment, "Environment must not be null");
this.registry = registry;
this.conditionEvaluator = new ConditionEvaluator(registry, environment, null);
// 注入常见的后处理器
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
如下,总共会注入5个处理器
-
ConfigurationClassPostProcessor
主要处理@Component注解配置,注入beanDefinition -
AutowiredAnnotationBeanPostProcessor
主要处理bean属性上和方法上的@Autowired/@Value,注入依赖。 -
CommonAnnotationBeanPostProcessor
主要处理bean属性上的@Resource,注入依赖。 -
EventListenerMethodProcessor
主要处理bean方法上的@EventListener,注册为ApplicationListener,添加到ApplicationContext中。 -
DefaultEventListenerFactory
public static Set<BeanDefinitionHolder> registerAnnotationConfigProcessors(
BeanDefinitionRegistry registry, @Nullable Object source)
DefaultListableBeanFactory beanFactory = unwrapDefaultListableBeanFactory(registry);
if (beanFactory != null)
if (!(beanFactory.getDependencyComparator() instanceof AnnotationAwareOrderComparator))
beanFactory.setDependencyComparator(AnnotationAwareOrderComparator.INSTANCE);
if (!(beanFactory.getAutowireCandidateResolver() instanceof ContextAnnotationAutowireCandidateResolver))
beanFactory.setAutowireCandidateResolver(new ContextAnnotationAutowireCandidateResolver());
Set<BeanDefinitionHolder> beanDefs = new LinkedHashSet<>(8);
if (!registry.containsBeanDefinition(CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME))
RootBeanDefinition def = new RootBeanDefinition(ConfigurationClassPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, CONFIGURATION_ANNOTATION_PROCESSOR_BEAN_NAME));
if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME))
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME))
RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME))
RootBeanDefinition def = new RootBeanDefinition();
try
def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
AnnotationConfigUtils.class.getClassLoader()));
catch (ClassNotFoundException ex)
throw new IllegalStateException(
"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
if (!registry.containsBeanDefinition(EVENT_LISTENER_PROCESSOR_BEAN_NAME))
RootBeanDefinition def = new RootBeanDefinition(EventListenerMethodProcessor.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_PROCESSOR_BEAN_NAME));
if (!registry.containsBeanDefinition(EVENT_LISTENER_FACTORY_BEAN_NAME))
RootBeanDefinition def = new RootBeanDefinition(DefaultEventListenerFactory.class);
def.setSource(source);
beanDefs.add(registerPostProcessor(registry, def, EVENT_LISTENER_FACTORY_BEAN_NAME));
return beanDefs;
3. 注册main方法所在类
当调用BeanDefinitionLoader.load时,会将main方法所在类注册到BeanDefinitionRegistry,也就是当前AnnotationConfigServletWebServerApplicationContext。
4. 刷新上下文
// org.springframework.context.support.AbstractApplicationContext#refresh
@Override
public void refresh() throws BeansException, IllegalStateException
synchronized (this.startupShutdownMonitor)
StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
// (1) 构建beanFactory,load bean definition等等
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
beanPostProcess.end();
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
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();
contextRefresh.end();
4.1 获取刷新BeanFactory
obtainFreshBeanFactory分为两步,先刷新,再后取。在AbstractApplicationContext定义好了这两个抽象方法。
//org.springframework.context.support.AbstractApplicationContext#obtainFreshBeanFactory
protected ConfigurableListableBeanFactory obtainFreshBeanFactory()
refreshBeanFactory();
return getBeanFactory();
protected abstract void refreshBeanFactory() throws BeansException, IllegalStateException;
protected abstract void closeBeanFactory();
@Override
public abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;
实现类有两个,一个是可刷新的,需要在子类中实现loadBeanDefinitions方法,一般是加载类型比较确定的,例如xml/config等,一般是在调用refresh后,才有getBeanFactory才非空。org.springframework.context.support.AbstractRefreshableApplicationContext#refreshBeanFactory;
4.1.1 可重复构建BeanFactory
可刷新的ApplicationContext,需要在子类中实现loadBeanDefinitions方法,一般是加载类型比较确定的,例如xml/config等,一般是在调用refresh后,才有getBeanFactory才非空。org.springframework.context.support.AbstractRefreshableApplicationContext#refreshBeanFactory;
@Override
protected final void refreshBeanFactory() throws BeansException
if (hasBeanFactory())
destroyBeans();
closeBeanFactory();
try
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
// 核心
loadBeanDefinitions(beanFactory);
this.beanFactory = beanFactory;
catch (IOException ex)
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
@Override
public final ConfigurableListableBeanFactory getBeanFactory()
DefaultListableBeanFactory beanFactory = this.beanFactory;
if (beanFactory == null)
throw new IllegalStateException("BeanFactory not initialized or already closed - " +
"call 'refresh' before accessing beans via the ApplicationContext");
return beanFactory;
对应的子类有,loadBeanDefinitions如何实现?
AbstractXmlApplicationContext,需要子类设置configLocations等配置文件。
// org.springframework.context.support.AbstractXmlApplicationContext
/**
* Loads the bean definitions via an XmlBeanDefinitionReader.
* @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
* @see #initBeanDefinitionReader
* @see #loadBeanDefinitions
*/
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// Configure the bean definition reader with this context's
// resource loading environment.
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
// Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the bean definitions.
initBeanDefinitionReader(beanDefinitionReader);
loadBeanDefinitions(beanDefinitionReader);
/**
* Initialize the bean definition reader used for loading the bean
* definitions of this context. Default implementation is empty.
* <p>Can be overridden in subclasses, e.g. for turning off XML validation
* or using a different XmlBeanDefinitionParser implementation.
* @param reader the bean definition reader used by this context
* @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader#setDocumentReaderClass
*/
protected void initBeanDefinitionReader(XmlBeanDefinitionReader reader)
reader.setValidating(this.validating);
/**
* Load the bean definitions with the given XmlBeanDefinitionReader.
* <p>The lifecycle of the bean factory is handled by the @link #refreshBeanFactory
* method; hence this method is just supposed to load and/or register bean definitions.
* @param reader the XmlBeanDefinitionReader to use
* @throws BeansException in case of bean registration errors
* @throws IOException if the required XML document isn't found
* @see #refreshBeanFactory
* @see #getConfigLocations
* @see #getResources
* @see #getResourcePatternResolver
*/
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException
Resource[] configResources = getConfigResources();
if (configResources != null)
reader.loadBeanDefinitions(configResources);
String[] configLocations = getConfigLocations();
if (configLocations != null)
reader.loadBeanDefinitions(configLocations);
AnnotationConfigWebApplicationContext,需要子类设置basePackages等包路径,也可以设置componentClasses
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)
AnnotatedBeanDefinitionReader reader = getAnnotatedBeanDefinitionReader(beanFactory);
ClassPathBeanDefinitionScanner scanner = getClassPathBeanDefinitionScanner(beanFactory);
BeanNameGenerator beanNameGenerator = getBeanNameGenerator();
if (beanNameGenerator != null)
reader.setBeanNameGenerator(beanNameGenerator);
scanner.setBeanNameGenerator(beanNameGenerator);
beanFactory.registerSingleton(AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR, beanNameGenerator);
ScopeMetadataResolver scopeMetadataResolver = getScopeMetadataResolver();
if (scopeMetadataResolver != null)
reader.setScopeMetadataResolver(scopeMetadataResolver);
scanner.setScopeMetadataResolver(scopeMetadataResolver);
if (!this.componentClasses.isEmpty())
if (logger.isDebugEnabled())
logger.debug("Registering component classes: [" +
StringUtils.collectionToCommaDelimitedString(this.componentClasses) + "]");
reader.register(ClassUtils.toClassArray(this.componentClasses));
if (!this.basePackages.isEmpty())
if (logger.isDebugEnabled())
logger.debug("Scanning base packages: [" +
StringUtils.collectionToCommaDelimitedString(this.basePackages) + "]");
scanner.scan(StringUtils.toStringArray(this.basePackages));
String[] configLocations = getConfigLocations();
if (configLocations != null)
for (String configLocation : configLocations)
try
Class<?> clazz = ClassUtils.forName(configLocation, getClassLoader());
if (logger.isTraceEnabled())
logger.trace("Registering [" + configLocation + "]");
reader.register(clazz);
catch (ClassNotFoundException ex)
if (logger.isTraceEnabled())
logger.trace("Could not load class for config location [" + configLocation +
"] - trying package scan. " + ex);
int count = scanner.scan(configLocation);
if (count == 0 && logger.isDebugEnabled())
logger.debug("No component classes found for specified class/package [" + configLocation + "]");
4.1.2 不可重复构建BeanFactory
一个是不能刷新的,在构造函数时,已经就构建了BeanFactory。org.springframework.context.support.GenericApplicationContext#refreshBeanFactory。
@Override
protected final void refreshBeanFactory() throws IllegalStateException
if (!this.refreshed.compareAndSet(false, true))
throw new IllegalStateException(
"GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
this.beanFactory.setSerializationId(getId());
@Override
public final ConfigurableListableBeanFactory getBeanFactory()
return this.beanFactory;
GenericApplicationContext主要的子类如下,SpringBoot使用的AnnotationConfigServletWebServerApplicationContext该子类之一。所以这里其实刷新也没什么实际逻辑,就是设置了序列化id,而且有刷新标识,只能调用一次。
事实上,默认springBoot的所有ApplicationContext均是GenericApplicationContext的子类:
// org.springframework.boot.ApplicationContextFactory
ApplicationContextFactory DEFAULT = (webApplicationType) ->
try
switch (webApplicationType)
case SERVLET:
return new AnnotationConfigServletWebServerApplicationContext();
case REACTIVE:
return new AnnotationConfigReactiveWebServerApplicationContext();
default:
return new AnnotationConfigApplicationContext();
catch (Exception ex)
throw new IllegalStateException("Unable create a default ApplicationContext instance, "
+ "you may need a custom ApplicationContextFactory", ex);
;
4.2 prepareBeanFactory
这一步,主要是对BeanFactory进行配置,设置ApplicationContextAwareProcessor,注入一些常见的依赖解析,包括beanFactory,ApplicationContext,ResourceLoader、Environment等。
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory)
// Tell the internal bean factory to use the context's class loader etc.
beanFactory.setBeanClassLoader(getClassLoader());
if (!shouldIgnoreSpel)
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
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.ignoreDependencyInterface(ApplicationStartupAware.class);
// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
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.
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (!NativeDetector.inNativeImage() && 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());
if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME))
beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
其中ApplicationContextAwareProcessor
class ApplicationContextAwareProcessor implements BeanPostProcessor
@Override
@Nullable
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException
invokeAwareInterfaces(bean);
return bean;
private void invokeAwareInterfaces(Object bean)
if (bean instanceof EnvironmentAware)
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
if (bean instanceof EmbeddedValueResolverAware)
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
if (bean instanceof ResourceLoaderAware)
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
if (bean instanceof ApplicationEventPublisherAware)
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
if (bean instanceof MessageSourceAware)
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
if (bean instanceof ApplicationStartupAware)
((ApplicationStartupAware) bean).setApplicationStartup(this.applicationContext.getApplicationStartup());
if (bean instanceof ApplicationContextAware)
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
4.3 postProcessBeanFactory
主要是注入WebApplicationContextServletContextAwareProcessor,支持ServletContextAware/ServletConfigAware,之后扫描basePackages,注册注解类,但是这后面两步一般都是空操作。
// 父类:org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#postProcessBeanFactory
/**
* Register ServletContextAwareProcessor.
* @see ServletContextAwareProcessor
*/
@Override
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
beanFactory.addBeanPostProcessor(new WebApplicationContextServletContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(ServletContextAware.class);
registerWebApplicationScopes();
// 子类:org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext#postProcessBeanFactory
@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));
4.4 invokeBeanFactoryPostProcessors
主要是使用BeanFactoryPostProcessor对BeanFactory进行初始化,这个步骤非常重要,对于注解配置,会扫描注入所有符合条件的BeanDefinition,方便后续实例化单例bean。传递入参有:
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors)
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<>();
if (beanFactory instanceof BeanDefinitionRegistry)
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors)
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor)
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
else
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, beanFactory.getApplicationStartup());
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, beanFactory.getApplicationStartup());
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, beanFactory.getApplicationStartup());
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<>(orderedPostProcessorNames.size());
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<>(nonOrderedPostProcessorNames.size());
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();
处理步骤:
BeanDefinitionRegistryPostProcessor是BeanFactoryPostProcessor的子类。调用顺序如下,从这里也可以看出,一个Spring容器的BFPP/BPP,是不会共享给其他Spring容器,需要手动注册。
-
先对于BeanDefintionRegistryPostProcessor#postProcessBeanDefinitionRegistry()。
- 先调用手动添加到ApplicationContext中的BeanDefinitionRegistryPostProcessor
- 然后是容器中定义的BeanDefinitionRegistryPostProcessor,按照PriorityOrdered、Ordered、NonOrdered排序执行,相同情况下按照order值从小到大执行。
-
再BeanFactoryPostProcessor#postProcessBeanFactory()。
- 先调用手动添加到ApplicationContext中的BeanDefinitionRegistryPostProcessor#postProcessBeanFactory
- 然后是容器中定义的BeanDefinitionRegistryPostProcessor#postProcessBeanFactory,
- 对于手动添加的且只属于BeanFactoryPostProcessor,调用postProcessBeanFactory。
- 找到容器中定义的BeanFactoryPostProcessor,按照PriorityOrdered、Ordered、NonOrdered排序执行,相同情况下按照order值从小到大执行
CachingMetadataReaderFactoryPostProcessor主要是设置ConfigurationClassPostProcessor的setMetadataReaderFactory为SharedMetadataReaderFactoryBean,主要是对每个class resource,设置了缓存,见ConcurrentReferenceCachingMetadataReaderFactory
// org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer.CachingMetadataReaderFactoryPostProcessor#postProcessBeanDefinitionRegistry
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException
register(registry);
configureConfigurationClassPostProcessor(registry);
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer.ConfigurationWarningsPostProcessor,主要是对扫描org/org.springframework包进行警告。
ConfigurationClassPostProcessor处理所有配置类,注册为beanDefinition的过程,详细见:spring boot配置类注册深入解析
4.5 registerBeanPostProcessors
主要是从当前BeanFactory(不包含父BeanFactory)加载所有BeanPostProcessor,初始化,并设置到BeanFactory中。按照PriorityOrdered、Ordered、NonOrdered排序添加,相同情况下按照order值从小到大执行。BeanPostProcessor在bean的创建过程中生效。有4点需要注意:
- 先注册的BPP会应用到后注册的BPP中,但是手动添加的会一直生效。
- 由于BeanFactoryPostProcessor是在注册BeanPostProcessor之前实例化的,所以,BeanFactoryPostProcessor在被构建时,只有手动添加的会生效,其余的一律不生效。所以在BeanFactoryPostProcessor中使用@Value/@Resource等注解,不生效。
- 对于BeanFactoryPostProcessor和BeanPostProcessor由于会提前初始化,所以尽量不要在这些类里边使用其他依赖,例如@Resource,可能会造成依赖过早初始化,而缺乏相关@BeanPostProcessor的处理,例如无法生成代理,事务不生效等。
- 对于BeanFactoryPostProcessor和BeanPostProcessor由于会提前初始化,使用@Bean注册这类bean时,尽量声明为static,避免过早初始化宿主类,从而避免宿主类无法生成代理,事务不生效等问题。
初始化时,有下面四个BeanPostProcessor
4.6 初始化事件多播器
再这之前是初始化消息来源,支持国际化。初始化事件多播器默认底层使用的是SimpleApplicationEventMulticaster来实现。所有的ApplicationListener都会注册到这里
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() + "]");
4.7 onRefresh
这一步有两个作用:
- 初始化ThemeSource
- 对于springboot,则会创建tomcat,注册所有的servlet/filter等到tomcat servlet context。
关于tomcat的构建,详细见:spring boot启动加载tomcat原理深度剖析
//org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#onRefresh
@Override
protected void onRefresh()
super.onRefresh();
try
createWebServer();
catch (Throwable ex)
throw new ApplicationContextException("Unable to start web server", ex);
private void createWebServer()
WebServer webServer = this.webServer;
ServletContext servletContext = getServletContext();
if (webServer == null && servletContext == null)
StartupStep createWebServer = this.getApplicationStartup().start("spring.boot.webserver.create");
ServletWebServerFactory factory = getWebServerFactory();
createWebServer.tag("factory", factory.getClass().toString());
this.webServer = factory.getWebServer(getSelfInitializer());
createWebServer.end();
getBeanFactory().registerSingleton("webServerGracefulShutdown",
new WebServerGracefulShutdownLifecycle(this.webServer));
getBeanFactory().registerSingleton("webServerStartStop",
new WebServerStartStopLifecycle(this, this.webServer));
else if (servletContext != null)
try
getSelfInitializer().onStartup(servletContext);
catch (ServletException ex)
throw new ApplicationContextException("Cannot initialize servlet context", ex);
initPropertySources();
4.8 注册所有ApplicationListener到事件多播器
主要是注册手动加入的ApplicationListener,然后从当前BeanFactory获取到ApplicationListener bean,添加到multicaster上,
// org.springframework.context.support.AbstractApplicationContext#registerListeners
/**
* 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 (!CollectionUtils.isEmpty(earlyEventsToProcess))
for (ApplicationEvent earlyEvent : earlyEventsToProcess)
getApplicationEventMulticaster().multicastEvent(earlyEvent);
早期手动添加的ApplicationListener
当前BeanFactory拥有的ApplicationListener bean:
4.9 非懒单例提前加载
主要是两个作用:
- 获取所有的非懒单例bean,getBean构建
- 当所有单例bean加载完毕后,对于实现SmartInitializingSingleton接口的单例bean,调用其afterSingletonsInstantiated方法。
// org.springframework.context.support.AbstractApplicationContext#finishBeanFactoryInitialization
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 BeanFactoryPostProcessor
// (such as a PropertySourcesPlaceholderConfigurer 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();
// org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons
@Override
public void preInstantiateSingletons() throws BeansException
if (logger.isTraceEnabled())
logger.trace("Pre-instantiating singletons in " + this);
// Iterate over a copy to allow for init methods which in turn register new bean definitions.
// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames)
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit())
if (isFactoryBean(beanName))
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean)
FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean)
isEagerInit = AccessController.doPrivileged(
(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
else
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
if (isEagerInit)
getBean(beanName);
else
getBean(beanName);
// Trigger post-initialization callback for all applicable beans...
for (String beanName : beanNames)
Object singletonInstance = getSingleton(beanName);
if (singletonInstance instanceof SmartInitializingSingleton)
StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize")
.tag("beanName", beanName);
SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
if (System.getSecurityManager() != null)
AccessController.doPrivileged((PrivilegedAction<Object>) () ->
smartSingleton.afterSingletonsInstantiated();
return null;
, getAccessControlContext());
else
smartSingleton.afterSingletonsInstantiated();
smartInitialize.end();
实现SmartInitializingSingleton接口的,主要有EventListenerMethodProcessor、AnnotationMBeanExporter、org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration.SameManagementContextConfiguration
todo 补充这里的使用情况。
4.10 完成刷新
- 初始化生命周期处理器,一般默认是DefaultLifecycleProcessor
- 调用所有的生命周期bean,实现Lifecycle接口,调用其start()。依据spring容器启动后和关闭前,需要实现SmartLifecycle,该类中isAutoStartup()返回true,表示自动在app.finishRefresh()/app.onDestroy()触发调用
- 发送ContextRefreshedEvent事件,表示容器启动成功。注意,如果当前容器有parent容器,则也会向parent容器发送该事件。
- 非原生镜像时,注册当前ApplicationContext作为MBean,只能注册一次。
以上是关于spring ApplicationContext启动过程的主要内容,如果未能解决你的问题,请参考以下文章
Spring -- Spring相关API (ApplicationContext getBean)
spring BeanFactory 与ApplicationContext
BeanFactory and ApplicationContext in Spring