spring启动流程 (1) 流程概览
本文将通过阅读AnnotationConfigApplicationContext源码,分析Spring启动流程。
创建AnnotationConfigApplicationContext
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
applicationContext.register(XxConfig.class);
applicationContext.register(YyConfig.class);
applicationContext.refresh();
XxService xxService = applicationContext.getBean(XxService.class);
核心的启动逻辑都在refresh方法中。
构造方法
public AnnotationConfigApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
AnnotatedBeanDefinitionReader类
定义了多个register方法,用于向Spring容器注册BeanDefinition。
在创建AnnotatedBeanDefinitionReader时,会向容器注册几个注解驱动处理器:
- org.springframework.context.annotation.internalConfigurationAnnotationProcessor: ConfigurationClassPostProcessor
- BeanFactoryPostProcessor实现,用于解析@Configuration类。
- 按优先级排序,因为在@Configuration类中声明的任何@Bean方法都必须在任何其他BeanFactoryPostProcessor执行之前注册其对应的BeanDefinition。
- org.springframework.context.annotation.internalAutowiredAnnotationProcessor: AutowiredAnnotationBeanPostProcessor
- BeanPostProcessor实现类。
- @Autowired支持处理器。
- org.springframework.context.annotation.internalCommonAnnotationProcessor: CommonAnnotationBeanPostProcessor
- BeanPostProcessor实现类。
- 支持Resource、PostConstruct、PreDestroy等注解。
- org.springframework.context.event.internalEventListenerProcessor: EventListenerMethodProcessor
- org.springframework.context.event.internalEventListenerFactory: DefaultEventListenerFactory
ClassPathBeanDefinitionScanner类
BeanDefinition扫描器,在类路径上检测Bean,并将其注册到Spring容器中。扫描的类是通过类型过滤器检测到的。
refresh方法
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
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);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// 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) {
// 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();
}
}
}
prepareRefresh方法
Prepare this context for refreshing, setting its startup date and active flag as well as performing any initialization of property sources.
protected void prepareRefresh() {
// Switch to active.
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
// Initialize any placeholder property sources in the context environment.
// Replace any stub property sources with actual instances.
// web相关的ApplicationContext有实现
initPropertySources();
// Validate that all properties marked as required are resolvable:
// see ConfigurablePropertyResolver#setRequiredProperties
getEnvironment().validateRequiredProperties();
// Store pre-refresh ApplicationListeners...
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
} else {
// Reset local application listeners to pre-refresh state.
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
this.earlyApplicationEvents = new LinkedHashSet<>();
}
obtainFreshBeanFactory方法
Tell the subclass to refresh the internal bean factory.
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
refreshBeanFactory();
return getBeanFactory();
}
由于AnnotationConfigApplicationContext继承了GenericApplicationContext类,所以此处获取到的是DefaultListableBeanFactory对象。
prepareBeanFactory方法
配置BeanFactory的标准上下文,例如上下文的ClassLoader和后置处理器。
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
beanFactory.setBeanClassLoader(getClassLoader());
// Standard implementation of the BeanExpressionResolver interface,
// parsing and evaluating Spring EL using Spring's expression module.
beanFactory.setBeanExpressionResolver(
new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// Configure the bean factory with context callbacks.
// 支持EnvironmentAware, MessageSourceAware, ApplicationContextAware等
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 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);
// ApplicationListenerDetector处理器自动将ApplicationListener类型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()));
}
// 注册env bean
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());
}
}
postProcessBeanFactory方法
Modify the application context's internal bean factory after its standard initialization. All bean definitions will have been loaded, but no beans will have been instantiated yet. This allows for registering special BeanPostProcessors etc in certain ApplicationContext implementations.
在标准初始化之后修改ApplicationContext的内部bean工厂。所有的BeanDefinition都将被加载,但还没有任何Bean被实例化。这允许在某些ApplicationContext实现中注册特殊的BeanPostProcessors等。
invokeBeanFactoryPostProcessors方法
实例化并调用注册的所有BeanFactoryPostProcessor,如果指定顺序则按照顺序调用,必须在单例实例化之前调用。
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
// 调用BeanFactoryPostProcessors
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和BeanDefinitionRegistryPostProcessor。
registerBeanPostProcessors方法
实例化并注册所有BeanPostProcessor,如果指定顺序则按照顺序注册,必须在应用Bean实例化之前调用。
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}
把BeanPostProcessor实例添加到beanPostProcessors中:
- 从容器获取所有的BeanPostProcessor Bean
- 按照以下顺序注册:实现了PriorityOrdered接口、实现了Ordered接口、普通BeanPostProcessor、实现MergedBeanDefinitionPostProcessor接口
private static void registerBeanPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {
for (BeanPostProcessor postProcessor : postProcessors) {
beanFactory.addBeanPostProcessor(postProcessor);
}
}
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());
}
}
} 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);
}
}
initApplicationEventMulticaster方法
初始化ApplicationEventMultimaster,如果Context中未定义,则使用SimpleApplicationEventMultimaster。
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);
} else {
this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
beanFactory.registerSingleton(
APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
}
}
onRefresh方法
可以重写的模板方法,以添加指定的刷新逻辑。在初始化特殊Bean时调用,在实例化单例之前调用。
默认什么都不做。
SpringBoot中的ServletWebServerApplicationContext实现类在这个阶段创建WebServer。
registerListeners方法
添加实现ApplicationListener的Bean作为侦听器。不会影响其他侦听器,这些侦听器可以在不使用Bean的情况下添加。
finishBeanFactoryInitialization方法
完成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();
}
finishRefresh方法
完成刷新工作,调用LifecycleProcessor的onRefresh()方法并发布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);
}
启动流程
- 创建AnnotationConfigApplicationContext对象
- 创建AnnotatedBeanDefinitionReader和ClassPathBeanDefinitionScanner
- 向容器注册几个注解驱动处理器:ConfigurationClassPostProcessor, AutowiredAnnotationBeanPostProcessor, CommonAnnotationBeanPostProcessor等
- 调用applicationContext.register(XxConfig.class)注册配置类
- 调用refresh()方法:
- prepareRefresh方法准备工作:初始化PropertySources、validateRequiredProperties等
- Refresh the internal beanFactory
- 配置BeanFactory的标准上下文,例如上下文的ClassLoader和后置处理器
- 实例化并调用注册的所有BeanFactoryPostProcessor,如果指定顺序则按照顺序调用,必须在单例实例化之前调用
- 实例化并注册所有BeanPostProcessor,如果指定顺序则按照顺序注册,必须在应用Bean实例化之前调用
- 初始化MessageSource
- 初始化ApplicationEventMultimaster,如果Context中未定义,则使用SimpleApplicationEventMultimaster
- onRefresh方法,SpringBoot中的ServletWebServerApplicationContext实现类在这个阶段创建WebServer
- 添加实现ApplicationListener的Bean作为侦听器
- 完成Bean工厂的初始化,初始化所有剩余的单例Bean
- 完成刷新工作,调用LifecycleProcessor的onRefresh()方法并发布ContextRefreshedEvent事件
spring启动流程 (1) 流程概览的更多相关文章
- SSH(Struts2+Spring+Hibernate)框架搭建流程<注解的方式创建Bean>
此篇讲的是MyEclipse9工具提供的支持搭建自加包有代码也是相同:用户登录与注册的例子,表字段只有name,password. SSH,xml方式搭建文章链接地址:http://www.cnblo ...
- SpringMVC启动和执行流程
Spring框架大家用得很多,相当熟悉,但是我对里面的运作比较好奇,例如bean的加载和使用,和我们定义的配置文件有什么联系;又例如aop在什么时候起作用,原理又是怎样.经过一个了解后,整理了启动和执 ...
- Spring Boot 自动装配流程
Spring Boot 自动装配流程 本文以 mybatis-spring-boot-starter 为例简单分析 Spring Boot 的自动装配流程. Spring Boot 发现自动配置类 这 ...
- 【Java面试】介绍下Spring IoC的工作流程
Hi,我是Mic 一个工作了4年的粉丝,在面试的时候遇到一个这样的问题. "介绍一下Spring IOC的工作流程" 他说回答得不是很好,希望我能帮他梳理一下. 关于这个问题,我们 ...
- Spring MVC的运行流程
Spring MVC的运行流程 摘要:本文档主要结合官方给出的Spring MVC流程图结合一个简单的Spring MVC实例,分析并介绍了Spring MVC的运行流程. 目录 Spring MVC ...
- 最简单易懂的Spring Security 身份认证流程讲解
最简单易懂的Spring Security 身份认证流程讲解 导言 相信大伙对Spring Security这个框架又爱又恨,爱它的强大,恨它的繁琐,其实这是一个误区,Spring Security确 ...
- 《转》深入理解Activity启动流程(三)–Activity启动的详细流程2
本文原创作者:Cloud Chou. 出处:本文链接 本系列博客将详细阐述Activity的启动流程,这些博客基于Cm 10.1源码研究. 深入理解Activity启动流程(一)--Activity启 ...
- 《转》深入理解Activity启动流程(三)–Activity启动的详细流程1
本文原创作者:Cloud Chou. 出处:本文链接 本系列博客将详细阐述Activity的启动流程,这些博客基于Cm 10.1源码研究. 深入理解Activity启动流程(一)--Activity启 ...
- 《转》深入理解Activity启动流程(一)–Activity启动的概要流程
本文原创作者:Cloud Chou. 原文地址:http://www.cloudchou.com/android/post-788.html Android中启动某个Activity,将先启动Acti ...
- 深入理解Activity启动流程(三)–Activity启动的详细流程2
本文原创作者:Cloud Chou. 欢迎转载,请注明出处和本文链接 本系列博客将详细阐述Activity的启动流程,这些博客基于Cm 10.1源码研究. 深入理解Activity启动流程(一)--A ...
随机推荐
- 组合式api-侦听器watch的语法
和vue2对比,也是语法上稍有不同. 监听单个数据对象 <script setup> import {ref, watch} from "vue"; const cou ...
- Scrapy在pipeline中集成mongodb
settings.py中设置配置项 MONGODB_HOST = "127.0.0.1" MONGODB_PORT = 27017 MONGODB_DB_NAME = " ...
- C++ Qt开发:Charts绘制各类图表详解
Qt 是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍TreeWid ...
- 【难受】SpirngCloud-Alibaba-nacos跨服务器访问接口的问题
原想法:我首先准备了 一个网关 2个服务 分别将两个服务部署到不同的远程服务器当中 实现跨服务器访问接口 网关为本地调用--这里就不一一介绍了 问题 利用gateway做路由时出现服务不可用的情况,看 ...
- Ubuntu20.04 安装shutter
1 sudo add-apt-repository ppa:linuxuprising/shutter 2 3 sudo apt install shutter 4 5 卸载 6 sudo apt-g ...
- 如何使用.NET在2.2秒内处理10亿行数据(1brc挑战)
译者注 在上周我就关注到了在github上有1brc这样一个挑战,当时看到了由Victor Baybekov提交了.NET下最快的实现,当时计划抽时间写一篇文章解析他的代码实现,今天突然看到作者自己写 ...
- 云图说|新一代Serverless应用托管引擎——CAE
本文分享自华为云社区<云图说|新一代Serverless应用托管引擎--CAE>,作者:阅识风云. 开发运营一个应用软件,面临种种挑战:软件栈厚重.开发上线慢.资源易浪费.运维投入高.突发 ...
- 华为云发布CodeArts APIMock服务,精准Mock,并行开发零等待!
本文分享自华为云社区<华为云发布CodeArts APIMock服务,精准Mock,并行开发零等待!>,作者: 华为云头条. 2023年10月10日,华为云正式发布CodeArts API ...
- 什么是VXLAN?为什么需要VXLAN?
摘要:本文介绍了什么是VXLAN,以及VXLAN的基本概念和工作原理,包括:为什么需要VXLAN?VXLAN与VLAN之间有啥不同?什么是VTEP?什么是VNI?VXLAN报文是如何封装的?VXLAN ...
- 实践GoF的设计模式:访问者模式
摘要:访问者模式的目的是,解耦数据结构和算法,使得系统能够在不改变现有代码结构的基础上,为对象新增一种新的操作. 本文分享自华为云社区<[Go实现]实践GoF的23种设计模式:访问者模式> ...