SpringBean容器启动流程+Bean的生命周期【附源码】
如果对SpringIoc与Aop的源码感兴趣,可以访问参考:https://javadoop.com/,十分详细。
Spring容器的启动全流程
Spring容器的启动流程如下,这是我在看源码过程中自己总结的流程图,如有错误,还望评论区指点:

接下来附上源码:
为什么是refresh方法命名,而不是init命名呢?
其实,在ApplicaitonContext建立起来之后,可以通过refresh进行重建,将原来的ac销毁,重新执行一次初始化操作,用refresh更加贴切。
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
//如果已经有application Context ,并需要配置成父子关系, 调用该构造方法
super(parent);
// 根据提供的路径,处理成配置文件数组(以分号、逗号、空格、tab、换行符分割)
setConfigLocations(configLocations);
if (refresh) {
refresh();//核心!!!
}
}
虽然ApplicationContext继承自BeanFactory,更确切地说是ApplicationContext内部持有了一个实例化的BeanFactory(DefaultListableBeanFactory),BeanFactory的相关操作其实是委托给这个实例来处理。
@Override
public void refresh() throws BeansException, IllegalStateException {
//保证容器启动销毁操作的并发安全
synchronized (this.startupShutdownMonitor) {
//准备工作, 记录容器的启动时间, 标记已启动状态, 处理配置文件种的占位符
prepareRefresh();
//这步用于将配置文件解析成一个个bean definition,注册到重建的beanFactory中,(只是提取了配置信息,bean并没有初始化),同时还设置两个配置属性:1、是否允许bean覆盖2、是否允许循环引用
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//设置beanFactory的类加载器, 添加几个beanPostProcessor ,手动注册几个特殊的bean
prepareBeanFactory(beanFactory);
try {
//如果bean实现了beanFactoryPostProcessor 将会执行postProcessBeanFactory方法 提供子类的扩展点,到这bean都加载、注册完成,但没有初始化,具体的子类可以在这步添加特殊bfpp实现类做事
postProcessBeanFactory(beanFactory);
//调用bfpp的各个实现类的ppbf方法
invokeBeanFactoryPostProcessors(beanFactory);
//注册BeanPostProcessor的实现类,BeanPostProcessor将在bean初始化前后执行
registerBeanPostProcessors(beanFactory);
//初始化当前 ApplicationContext 的 MessageSource,国际化
initMessageSource();
//初始化当前 ApplicationContext 的事件广播器
initApplicationEventMulticaster();
//模板方法(钩子方法,具体的子类可以在这里初始化一些特殊的 Bean(在初始化 singleton beans 之前)
onRefresh();
//注册事件监听器,监听器需要实现 ApplicationListener 接口。
registerListeners();
//实例化+初始化所有的非懒加载的单例bean
finishBeanFactoryInitialization(beanFactory);
//广播事件,ApplicationContext 初始化完成
finishRefresh();
}
catch (BeansException ex) {
// Destroy already created singletons to avoid dangling resources.销毁已经初始化的 singleton 的 Beans,以免有些 bean 会一直占用资源
destroyBeans();
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
resetCommonCaches();
}
}
}
利用注解方式大致也是按照这个流程一步步下来,不同在于,AnnotationConfigApplicationContext在执行构造器的时候,已经通过scan(basePackages);将beanDefination读取到。
将bean的定义转化为BeanDefination:
如果利用AnnotationConfigApplicationContext。
public AnnotationConfigApplicationContext(String... basePackages) {
this();
scan(basePackages);//这个过程中配置已经被转化为一个个的beanDefinition
refresh();
}
Spring容器关闭流程
protected void doClose() {
if (this.active.get() && this.closed.compareAndSet(false, true)) {
if (logger.isDebugEnabled()) {
logger.debug("Closing " + this);
}
//取消注册上下文
if (!IN_NATIVE_IMAGE) {
LiveBeansView.unregisterApplicationContext(this);
}
// 发布事件
publishEvent(new ContextClosedEvent(this));
// 停止所有Lifecycle bean,以避免在销毁期间造成延迟。
if (this.lifecycleProcessor != null) {
this.lifecycleProcessor.onClose();
}
// 销毁上下文的BeanFactory中所有缓存的单例。
destroyBeans();
// 关闭此上下文本身的状态。
closeBeanFactory();
// 让子类善后
onClose();
// 充值本地应用坚硬其为pre-refresh状态
if (this.earlyApplicationListeners != null) {
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}
// 切换为非活动状态
this.active.set(false);
}
}
大概就是:先发布事件,再摧毁Factory中的bean,再摧毁Factory本身,最后设置一些状态。
而Bean周期中的销毁部分就存在于destroyBeans中。当然,销毁bean也是需要先销毁它所依赖的bean。
Bean 的生命周期

在了解Bean的生命周期之前,我们必须要明确SpringBean和我们通常说的对象有什么区别?
SpringBean是由SpringIoC容器管理的,是一个被实例化,组装,并通过容器管理的对象,可通过getBean()获取。容器通过读取配置的元数据,解析成BeanDefinition,注册到BeanFactory中,加入到singletonObjects缓存池中。
Bean的创建
在上面的流程中,只有到finishBeanFactoryInitialization(beanFactory);这一步,才开始对非懒加载实例的实例化+ 初始化。
//实例化所有剩余的非懒加载的单例bean
beanFactory.preInstantiateSingletons();
可以看一下这一步的具体实现:DefaultListableBeanFactory
public void preInstantiateSingletons() throws BeansException {
//拥有所有的beanNames
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// 触发所有非懒加载的singleton beans的实例化+初始化操作
for (String beanName : beanNames) {
//对bean继承的处理,合并父bean 中的配置
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
//非抽象,非懒加载的singletons
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
//处理factoryBean
if (isFactoryBean(beanName)) {
//如果是factoryBean,在beanName钱加上&,再调用getBean方法
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
//判断当前 FactoryBean 是否是 SmartFactoryBean 的实现
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);//普通的bean,直接调用getBean进行实例化
}
}
}
}
只有!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()条件满足的时候,这一步才会进行实例化,另外,Spring还对其是否为FactoryBean进行判断,当然了,一般来说,最最普通的bean都会在最后一个else分支中进行实例化。
doGetBean全流程
这部分篇幅过长,我直接放上总结的流程图:

createBean
那么createBean又干了什么事呢,稍微看看就可以:
//省略许多异常处理的部分
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {//初始化阶段的args == null
RootBeanDefinition mbdToUse = mbd;
// 确保 BeanDefinition 中的 Class 被加载
Class<?> resolvedClass = resolveBeanClass(mbd, beanName);
if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {
mbdToUse = new RootBeanDefinition(mbd);
mbdToUse.setBeanClass(resolvedClass);
}
// 准备方法覆写它来自于 bean 定义中的 <lookup-method /> 和 <replaced-method />
mbdToUse.prepareMethodOverrides();
// 让 InstantiationAwareBeanPostProcessor 在这一步有机会返回代理
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
// 重头戏,创建 bean
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
return beanInstance;
}
我们的重点放在Object beanInstance = doCreateBean(beanName, mbdToUse, args);这一步上,我们已经知道,Bean的实例化+初始化都在这一步中完成。
doCreateBean
在这个doCreateBean方法中,存在三个重要方法:
createBeanInstance 创建实例
protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
//确保已经加载了这个class
Class<?> beanClass = resolveBeanClass(mbd, beanName);
//校验这个类的访问权限
if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
throw new BeanCreationException();
}
//spring5.0 返回创建bean实例的回调
Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
if (instanceSupplier != null) {
return obtainFromSupplier(instanceSupplier, beanName);
}
if (mbd.getFactoryMethodName() != null) {
//采用工厂方法实例化
return instantiateUsingFactoryMethod(beanName, mbd, args);
}
// 如果是第二次创建 如prototype bean,这种情况下,我们可以从第一次创建知道,采用无参构造函数,还是构造函数依赖注入 来完成实例化
boolean resolved = false;
boolean autowireNecessary = false;
if (args == null) {
synchronized (mbd.constructorArgumentLock) {
if (mbd.resolvedConstructorOrFactoryMethod != null) {
resolved = true;
autowireNecessary = mbd.constructorArgumentsResolved;
}
}
}
if (resolved) {
if (autowireNecessary) {
//构造函数注入
return autowireConstructor(beanName, mbd, null, null);
}
else {
//无参构造函数
return instantiateBean(beanName, mbd);
}
}
// 判断是否采用有参构造函数
Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
//args!=null 的构造函数注入(有参)
return autowireConstructor(beanName, mbd, ctors, args);
}
// Preferred constructors for default construction?
ctors = mbd.getPreferredConstructors();
if (ctors != null) {
//判断是否采用首选的构造函数
return autowireConstructor(beanName, mbd, ctors, null);
}
// 调用无参构造函数
return instantiateBean(beanName, mbd);
}
以无参构造函数为例,实例化的过程在SimpleInstantiationStrategy中。
- 如果不存在方法重写:可以直接使用Java的反射进行实例化。
- 否则使用CGLIB实现实例化。
public Object instantiate(RootBeanDefinition bd, @Nullable String beanName, BeanFactory owner) {
// 如果不存在方法覆写,就是用java的反射进行实例化, 否则使用CGLIB
if (!bd.hasMethodOverrides()) {
Constructor<?> constructorToUse;
synchronized (bd.constructorArgumentLock) {
constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
if (constructorToUse == null) {
final Class<?> clazz = bd.getBeanClass();
if (clazz.isInterface()) {
throw new BeanInstantiationException(clazz, "Specified class is an interface");
}
try {
if (System.getSecurityManager() != null) {
constructorToUse = AccessController.doPrivileged(
(PrivilegedExceptionAction<Constructor<?>>) clazz::getDeclaredConstructor);
}
else {
constructorToUse = clazz.getDeclaredConstructor();
}
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Throwable ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
//利用构造方法进行实例化
return BeanUtils.instantiateClass(constructorToUse);
}
else {
// 存在方法覆写的情况,需要利用CGLIB来完成实例化,需要依赖于CGLIB生成子类
return instantiateWithMethodInjection(bd, beanName, owner);
}
}
此时,Bean实例已经通过构造方法或者工厂方法创建,但是其中的属性,如依赖注入的各种属性尚未填充。
populateBean 填充属性
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
if (bw == null) {
if (mbd.hasPropertyValues()) {//this.propertyValues bean实例的所有属性
throw new BeanCreationException(
mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
}
else {
// Skip property population phase for null instance.
return;
}
}
//在设置属性之前,给所有InstantiationAwareBeanPostProcessor机会修改bean的状态
// 【此时bean的状态 = 已经通过工厂方法或者构造方法实例化,在属性赋值之前】。例如,可以使用支持字段注入的样式。InstantiationAwareBeanPostProcessor
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
for (InstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().instantiationAware) {
if (!bp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
return;
}
}
}
PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);//获取PropertyValue对象
int resolvedAutowireMode = mbd.getResolvedAutowireMode();
if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {//获取Autowire的模式 or 通过名字, or 通过类型
MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
// 通过名字找到所有属性值,如果是 bean 依赖,先初始化依赖的 bean。记录依赖关系
if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {
autowireByName(beanName, mbd, bw, newPvs);
}
// 通过类型装配 记录依赖关系
if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {
autowireByType(beanName, mbd, bw, newPvs);
}
pvs = newPvs;
}
//...省略
//设置bean实例的属性值
if (pvs != null) {
applyPropertyValues(beanName, mbd, bw, pvs);
}
}
initializeBean 回调方法
属性注入完成,处理各种回调,如BeanNameAware、BeanClassLoaderAware、BeanFactoryAware等。
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {//
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);//如果bean实现了BeanNameAware、BeanClassLoaderAware、BeanFactoryAware接口, 回调
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);//BeanPostProcessor 的 postProcessBeforeInitialization 回调
}
try {
invokeInitMethods(beanName, wrappedBean, mbd);//处理bean中定义的init-method或 bean实现了InitializingBean ,调用afterPropertiesSet() 方法
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);//BeanPostProcessor 的 postProcessAfterInitialization 回调
}
return wrappedBean;
}
Bean的销毁
DisposableBeanAdapter.java
@Override
public void destroy() {
//CommonAnnotationBeanPostProcessorc 处理@preDetroy
if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
processor.postProcessBeforeDestruction(this.bean, this.beanName);
}
}
if (this.invokeDisposableBean) {////DisposableBean的destroy方法
((DisposableBean) this.bean).destroy();
}
}
if (this.destroyMethod != null) {//destroy-method方法
invokeCustomDestroyMethod(this.destroyMethod);
}
else if (this.destroyMethodName != null) {
Method methodToInvoke = determineDestroyMethod(this.destroyMethodName);
if (methodToInvoke != null) {
invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));
}
}
}
参考资料:
SpringBean容器启动流程+Bean的生命周期【附源码】的更多相关文章
- spring-第八篇之容器中的bean的生命周期
1.容器中的bean的生命周期 spring容器可以管理singleton作用域的bean的生命周期,包括bean何时被创建.何时初始化完成.何时被销毁.客户端代码不能控制该类型bean的销毁.spr ...
- drf复习(一)--原生djangoCBV请求生命周期源码分析、drf自定义配置文件、drf请求生命周期dispatch源码分析
admin后台注册model 一.原生djangoCBV请求生命周期源码分析 原生view的源码路径(django/views/generic/base.py) 1.从urls.py中as_view ...
- Spring Bean的生命周期 ---附详细流程图及测试代码
一.生命周期流程图: Spring Bean的完整生命周期从创建Spring容器开始,直到最终Spring容器销毁Bean,这其中包含了一系列关键点 假设一个Bean实现了所有的接口,大的概况一下Be ...
- SpringBoot的启动流程是怎样的?SpringBoot源码(七)
注:该源码分析对应SpringBoot版本为2.1.0.RELEASE 1 温故而知新 本篇接 SpringBoot内置的各种Starter是怎样构建的? SpringBoot源码(六) 温故而知新, ...
- OpenStack 虚拟机启动流程 UML 分析(内含 UML 源码)
目录 文章目录 目录 前言 API 请求 Nova API 阶段 Nova Conductor 阶段 Nova Scheduler 阶段 Nova Compute 阶段(计算节点资源分配部分) Nov ...
- 关于Application的onCreate以及Activity生命周期在源码里都是什么时候调用的
在ActivityThread.handleLaunchActivity中 Activity a = performLaunchActivity(r, customIntent);这一方法最终回调目标 ...
- (转)Spring管理的Bean的生命周期
http://blog.csdn.net/yerenyuan_pku/article/details/52834011 bean的初始化时机 前面讲解了Spring容器管理的bean的作用域.接着我们 ...
- Spring重点—— IOC 容器中 Bean 的生命周期
一.理解 Bean 的生命周期,对学习 Spring 的整个运行流程有极大的帮助. 二.在 IOC 容器中,Bean 的生命周期由 Spring IOC 容器进行管理. 三.在没有添加后置处理器的情况 ...
- IOC容器中bean的生命周期
一.Bean的生命周期 Spring IOC容器可以管理Bean的生命周期,允许在Bean生命周期的特定点执行定制的任务. Spring IOC容器对Bean的生命周期进行管理的过程如下: (1).通 ...
随机推荐
- java中ThrealLocal的理解
目录 java中threadlocal的理解 一.threadlocal的生命周期和ThreadLocalMap的生命周期 二.ThreadLocal的作用 三.threadlocal示例 四.Inh ...
- CTF bossplayers 靶机
WAYs: robots.txt文件提供线索,命令执行漏洞获得反弹shell suid命令提升权限 1:netdiscover 发现主机地址192.168.1.109 2:使用namp进行端口扫描发现 ...
- Ubuntu 16.04 sudo免密码visudo sudoers设置
使用sudo visudo调用nano对 /etc/sudoers 进行修改 $ sudo visudo 在想修改的对象最后加上 NOPASSWD: ALL 注意:在后面的设置会覆盖前面的设置
- 【SDOI2009】 HH的项链 - 莫队
题目描述 HH 有一串由各种漂亮的贝壳组成的项链.HH 相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义.HH 不断地收集新的贝壳,因此,他的项链变得越来越长. ...
- CSS动画实例:Loading加载动画效果(三)
3.小圆型Loading 这类Loading动画的基本思想是:在呈现容器中定义1个或多个子层,再对每个子层进行样式定义,使得其均显示为一个实心圆形,最后编写关键帧动画控制,使得各个实心圆或者大小发生改 ...
- ES7异步函数解决进程等待相关业务问题
业务需求场景描述: 在接口只能单一检测的情况下,批量检测资源名称是否存在数据库,如果资源群中某一个资源已存在:给出交互让用户决定是否覆盖资源,最后形成不存在的资源和用户确定覆盖的资源群,进行提交. 业 ...
- 将composer切换到国内镜像
composer config -g repo.packagist composer https://packagist.phpcomposer.com
- sqlalchemy怎么order_by降序/升序并取第一条数据
原文链接:https://blog.csdn.net/mark4541437/article/details/103755721 sqlalchemy怎么order_by降序/升序并取第一条数据 fr ...
- BIGI行情-实时行情数据源接口websocket接入方法
BIGI行情-实时行情数据源接口socket接入方法1.国际期货.国内期货.外汇.贵金属.现货.期权.股指.数字货币和A股实时行情和历史行情2.推送的有:socket,websocket,http接收 ...
- springboot整合druid监控配置
方式一:直接引入druid 1.maven坐标 <dependency> <groupId>com.alibaba</groupId> <artifactId ...