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

  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. Vue 函数式组件 functional

    函数式组件 无状态 无法实例化 内部没有任何生命周期处理函数 轻量,渲染性能高,适合只依赖于外部数据传递而变化的组件(展示组件,无逻辑和状态修改) 在template标签里标明functional 只 ...

  2. 安装黑苹果MoJave记录

    说实话安装黑苹果并不是一件很简单的事情,它既费时,而且还需要一定的计算机知识,最重要的是对于你来说可能黑苹果并没有Linux或者Windows好用. 好了废话不多说,开始吧. 1.硬件准备 并不是什么 ...

  3. 一进“dos”就自动进入上次的目录

    这个原来在别的地方发过,但是后来发现有bug,处理windows下带有空格的长文件夹会出错.因为原来那个帖子已经不能编辑了,所以修改后写在这里. 这里的“dos”,就是windows下的命令行窗口,所 ...

  4. Dubbo系列之 (四)服务订阅(1)

    辅助链接 Dubbo系列之 (一)SPI扩展 Dubbo系列之 (二)Registry注册中心-注册(1) Dubbo系列之 (三)Registry注册中心-注册(2) Dubbo系列之 (四)服务订 ...

  5. rcp

    rcp的命令 rcp,远程文件复制.rcp既可以在本地主机和远程主机之间进行文件复制,也可以用于在两个远程主机之间进行文件复制.除了复制文件外,rcp也可以用于目录复制,只需要加参数-r. rcp的命 ...

  6. Federated Learning with Matched Averaging

    挖个坑吧,督促自己仔细看一遍论文(ICLR 2020),看看自己什么时候也能中上那么一篇(流口水)~ 郑重声明:原文参见标题,如有侵权,请联系作者,将会撤销发布! Abstract 联邦学习允许边缘设 ...

  7. HTML5移动开发之路(1)——jqMobi中Side Menu实现(类似人人网)

    记得以前在做Native App的时候类似于人人网侧边滑动的效果非常的热,很多app仿照该效果进行开发,在jqMobi中也有类似的效果被称为Side Menu.下面我们来一步一步实现该效果. 首先新建 ...

  8. 牛客网PAT练兵场-人口普查

    题目地址:https://www.nowcoder.com/pat/6/problem/4054 题解:结构体排序即可 /** * Copyright(c) * All rights reserved ...

  9. [源码解析] Flink的Slot究竟是什么?(1)

    [源码解析] Flink的Slot究竟是什么?(1) 目录 [源码解析] Flink的Slot究竟是什么?(1) 0x00 摘要 0x01 概述 & 问题 1.1 Fllink工作原理 1.2 ...

  10. Docker 学习笔记(一)

    Docker 入门 Docker 学习 概述 安装 命令 镜像命令 容器命令 操作命令 Docker 镜像 容器数据卷 DockerFile Docker网络原理 IDEA 整合Docker 单机版D ...