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

文章目录

  • Spring容器的启动全流程
  • Spring容器关闭流程
  • Bean 的生命周期
    • Bean的创建
      • doGetBean全流程
      • createBean
      • doCreateBean
        • createBeanInstance 创建实例
        • populateBean 填充属性
        • initializeBean 回调方法
    • Bean的销毁

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 ,手动注册几个特殊的beanprepareBeanFactory(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();//实例化+初始化所有的非懒加载的单例beanfinishBeanFactoryInitialization(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);//这个过程中配置已经被转化为一个个的beanDefinitionrefresh();}

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 {//拥有所有的beanNamesList<String> beanNames = new ArrayList<>(this.beanDefinitionNames);// 触发所有非懒加载的singleton beans的实例化+初始化操作for (String beanName : beanNames) {//对bean继承的处理,合并父bean 中的配置RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);//非抽象,非懒加载的singletonsif (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {//处理factoryBeanif (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 == nullRootBeanDefinition 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;// 重头戏,创建 beanObject 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) {//确保已经加载了这个classClass<?> 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的反射进行实例化, 否则使用CGLIBif (!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的状态 = 已经通过工厂方法或者构造方法实例化,在属性赋值之前】。例如,可以使用支持字段注入的样式。InstantiationAwareBeanPostProcessorif (!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 处理@preDetroyif (!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));}}
}

参考资料:

  • https://javadoop.com/post/spring-ioc
  • https://www.cnblogs.com/mpyn/p/12134041.html
  • https://www.cnblogs.com/binghe001/p/13174687.html

Spring容器启动流程+Bean的生命周期【附源码】相关推荐

  1. Spring全家桶(四)Bean的生命周期

    十.Bean生命周期 10.1 Bean的生命周期 Spring IOC容器可以管理Bean的生命周期,也允许在Bean生命周期的特定点执行定制的任务. Spring IOC容器对Bean的生命周期进 ...

  2. 分析Spring容器启动流程 Spring初始化

    分析Spring容器启动流程 Spring初始化 每当启动Web容器时(例如Tomcat),会读取Web应用中的web.xml文件.以下这段代码就是启动Spring容器的关键代码. ContextLo ...

  3. php 变量存活期,php 变量生命周期:PHP源码分析-PHP的生_php

    php的最多的两种运行模式是web模式.CLI模式. 无论哪种模式,PHP工作原理都是一样的,作为一种SAPI运行. 1.当我们在终端敲入php这个命令的时候,它使用的是CLI. 它就像一个web服务 ...

  4. Spring IOC和Bean生命周期以及源码分析

    这篇文章主要讲解 IOC 容器的创建过程,让大家对整体有一个全局的认识,文章目录如图: 1. 基础知识 1.1 什么是 Spring IOC ? IOC 不是一种技术,只是一种思想,一个重要的面向对象 ...

  5. Spring学习总结1——bean的生命周期

    为什么80%的码农都做不了架构师?>>>    Spring实际上是一个容器框架,可以配置各种bean(action/service/domain/dao...),并且可以维护bea ...

  6. Spring高级应用之bean的生命周期

    简介: 在spring世界中,一切皆为bean,spring是面向bean编程的,bean也可以称为组件,是一个个java对象,多个组件间协调工作完成复杂的业务功能. 所以理解bean的生命周期,方便 ...

  7. spring入门第二讲 bean的生命周期 装配方式 Spring整合Junit

    bean的生命周期 实体类 //初始化 public void init(){System.out.println("--初始化--"); }//销毁 public void de ...

  8. 阿里面试真题:Spring容器启动流程

    有情怀,有干货,微信搜索[三太子敖丙]关注这个不一样的程序员. 本文 GitHub https://github.com/JavaFamily 已收录,有一线大厂面试完整考点.资料以及我的系列文章. ...

  9. activity 生命周期_Activity 源码解析

    Android 应用程序启动过程 Activity启动过程可以分为两种:一种是根activity的启动过程,另一种是普通activity启动过程.根activity指的是应用程序启动的第一个activ ...

最新文章

  1. 设计模式入门:建造者模式
  2. #HTTP协议学习# (二)基本认证
  3. 原创 | 变分自动编码器(VAE)
  4. 【错误记录】Android Studio 编译报错 ( This Gradle plugin requires a newer IDE able to request IDE model leve )
  5. TCP/IP报文格式
  6. BitMap算法应用:Redis队列滤重优化
  7. 我想在 2012 储备的技术
  8. kpmg java_【毕马威(KPMG)工资】java开发工程师待遇-看准网
  9. 获取DOM元素方法小结
  10. [Swift]LeetCode1020. 飞地的数量 | Number of Enclaves
  11. mac安装和卸载mysql_基于centos7系统卸载rpm安装的mysql
  12. JAVA进阶开发之(数组练习题)
  13. Visio连接线的箭头如何变为直线、双箭头;直线转换为箭头
  14. LGTM,XGBOOST,LIGHTGBM
  15. 1. 无穷维空间的测度论-Wiener测度(二)
  16. 单因素认证与多因素认证
  17. 程序员如何不加班?—— 时间管理篇
  18. 红帽linux默认用户名,RedHat Linux实现root身份的Telnet登录
  19. 过孔在覆铜后不出现十字孔
  20. 基于PHP美食食谱的外文翻译,中国传统菜谱的英文翻译锦集

热门文章

  1. layui数据表格搜索php代码,layui实现显示数据表格和搜索功能示例
  2. Unity实现磁铁效果
  3. 无线局域网WLAN扩展器工作模式
  4. 需求挖掘:产品经理怎么基于项目做需求挖掘
  5. 【翻译】Ext JS 6.6.0的新东西
  6. 220304-QQ管家工具箱“浏览器保护“”设置chrome谷歌浏览器为默认浏览器
  7. excel 2016生成汉字首拼字母小写
  8. python pyhook监听扫码_Python——pyHook监听鼠标键盘事件
  9. viper4android蓝牙耳机,手机也能听HiFi?VIPER 独占USB模式还原无损音质
  10. Visio画网络拓扑,平行线代替交叉线