SpringBean容器启动流程+Bean的生命周期【附源码】

时间:2022-11-05 11:05:30

如果对SpringIoc与Aop的源码感兴趣,可以访问参考:https://javadoop.com/,十分详细。

Spring容器的启动全流程

Spring容器的启动流程如下,这是我在看源码过程中自己总结的流程图,如有错误,还望评论区指点:

SpringBean容器启动流程+Bean的生命周期【附源码】

接下来附上源码:

为什么是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 的生命周期

SpringBean容器启动流程+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全流程

这部分篇幅过长,我直接放上总结的流程图:

SpringBean容器启动流程+Bean的生命周期【附源码】

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的生命周期【附源码】的更多相关文章

  1. spring-第八篇之容器中的bean的生命周期

    1.容器中的bean的生命周期 spring容器可以管理singleton作用域的bean的生命周期,包括bean何时被创建.何时初始化完成.何时被销毁.客户端代码不能控制该类型bean的销毁.spr ...

  2. drf复习(一)--原生djangoCBV请求生命周期源码分析、drf自定义配置文件、drf请求生命周期dispatch源码分析

    admin后台注册model  一.原生djangoCBV请求生命周期源码分析 原生view的源码路径(django/views/generic/base.py) 1.从urls.py中as_view ...

  3. Spring Bean的生命周期 ---附详细流程图及测试代码

    一.生命周期流程图: Spring Bean的完整生命周期从创建Spring容器开始,直到最终Spring容器销毁Bean,这其中包含了一系列关键点 假设一个Bean实现了所有的接口,大的概况一下Be ...

  4. SpringBoot的启动流程是怎样的?SpringBoot源码(七)

    注:该源码分析对应SpringBoot版本为2.1.0.RELEASE 1 温故而知新 本篇接 SpringBoot内置的各种Starter是怎样构建的? SpringBoot源码(六) 温故而知新, ...

  5. OpenStack 虚拟机启动流程 UML 分析(内含 UML 源码)

    目录 文章目录 目录 前言 API 请求 Nova API 阶段 Nova Conductor 阶段 Nova Scheduler 阶段 Nova Compute 阶段(计算节点资源分配部分) Nov ...

  6. 关于Application的onCreate以及Activity生命周期在源码里都是什么时候调用的

    在ActivityThread.handleLaunchActivity中 Activity a = performLaunchActivity(r, customIntent);这一方法最终回调目标 ...

  7. (转)Spring管理的Bean的生命周期

    http://blog.csdn.net/yerenyuan_pku/article/details/52834011 bean的初始化时机 前面讲解了Spring容器管理的bean的作用域.接着我们 ...

  8. Spring重点—— IOC 容器中 Bean 的生命周期

    一.理解 Bean 的生命周期,对学习 Spring 的整个运行流程有极大的帮助. 二.在 IOC 容器中,Bean 的生命周期由 Spring IOC 容器进行管理. 三.在没有添加后置处理器的情况 ...

  9. IOC容器中bean的生命周期

    一.Bean的生命周期 Spring IOC容器可以管理Bean的生命周期,允许在Bean生命周期的特定点执行定制的任务. Spring IOC容器对Bean的生命周期进行管理的过程如下: (1).通 ...

随机推荐

  1. python gutter area &sol; 设置断点、行号右边代码左边的空白栏

    最后通过在设置里搜索 关键词:show 找到的.== Edito > General > Gutter Icons Show gutter icons

  2. 更新centos curl

    centos curl 默认使用nss,而不是openssl 升级curl让curl支持openssl rpm -Uvh http://www.city-fan.org/ftp/contrib/yum ...

  3. Unity3d与iOS交互开发——接入平台SDK必备技能

    原地址:http://www.2cto.com/kf/201401/273337.html# 前言废话:开发手机游戏都知道,你要接入各种平台的SDK.那就需要Unity3d与iOS中Objective ...

  4. &lbrack;原创&rsqb;PostgreSQL Plus Advanced Server配合crontab实现定时维护工作

    本文要实现的目标1.PostgreSQL定时全备2.定时删除归档WAL文件3.定时删除全备文件4.删除n天之前的数据库日志文件 实验环境操作系统:RHEL 6.3数据库:PostgreSQL Plus ...

  5. Python 数据分析4

    本章概要 数据加载.存储与文件格式 数据加载.存储与文件格式 读取文本格式数据 read_csv 默认是按照逗号分割,也可设定其他分割符 df = pd.read_csv('file', sep='| ...

  6. Eclipse 创建maven项目 报错 one or more constraints have not been satisfied

    首先 在 pom.xml > plugins 中添加 <plugin> <groupId>org.apache.maven.plugins</groupId> ...

  7. 人工智能是如何改变IT运维和DevOps的?

    要解决IT运维和DevOps团队面对的挑战,就是能够在大量的日志数据流中识别潜在的小的有害问题,这正是认知洞察力所做的事情. 接下来的几年里,DevOps(开发软件工程.技术运营和质量保障三者的交集) ...

  8. Qt Image Water Marker

    QString str = "input.jpg"; if(!img.load(str)){ return; } QImage mark(img.width()/2,img.hei ...

  9. Ubuntu adb 报错:no permissions &lpar;user in plugdev group&semi; are your udev rules wrong&quest;&rpar;&semi;

    Ubuntu 下 adb 报错: caoxinyu@caoxinyu-ThinkPad-T470p:~/Android/Sdk/platform-tools$ ./adb devices List o ...

  10. HDU - 5997 树状数组&plus;set

    和之前一道省选题目很像: (梦幻布丁): 我们维护的时候用树状数组维护,在断电处打上标记: 合并的时候小的合并到大的里面: #include<iostream> #include<c ...