• Spring Bean 生命周期 (核心)(荣耀典藏版)


    目录

    前言

    一、获取Bean ​编辑

    第一阶段获取Bean

    二、创建Bean

    2. 创建Bean之前​编辑

    在真正创建Bean之前逻辑

    2.1 真正的创建Bean,doCreateBean​编辑

    doCreateBean方法逻辑

    2.1.1 实例化Bean,createBeanInstance

    实例化Bean

    2.1.2 填充Bean,populateBean​编辑

    填充Bean

    2.1.3 初始化Bean,initializeBean​编辑

    初始化Bean

    三、destory方法跟销毁Bean

    四、总结

    最后来一个大的流程

    实例化后

    初始化前


    前言

    大家好,我是程序缘--幻羽,我又来了!!

    在网上已经有跟多Bean的生命周期的博客,但是很多都是基于比较老的版本了,最近把整个流程化成了一个流程图。待会儿使用流程图,说明以及代码的形式来说明整个声明周期的流程。注意因为代码比较多,这里的流程图只画出了大概的流程,具体的可以深入代码。

    一、获取Bean 

     

    第一阶段获取Bean

    这里的流程图的入口在 AbstractBeanFactory类的 doGetBean方法,这里可以配合前面的 getBean方法分析文章进行阅读。主要流程就是

    1、先处理Bean 的名称,因为如果以“&”开头的Bean名称表示获取的是对应的FactoryBean对象;
    2、从缓存中获取单例Bean,有则进一步判断这个Bean是不是在创建中,如果是的就等待创建完毕,否则直接返回这个Bean对象
    3、如果不存在单例Bean缓存,则先进行循环依赖的解析
    4、解析完毕之后先获取父类BeanFactory,获取到了则调用父类的getBean方法,不存在则先合并然后创建Bean

    二、创建Bean

    2. 创建Bean之前

     

    在真正创建Bean之前逻辑

    这个流程图对应的代码在 AbstractAutowireCapableBeanFactory类的 createBean方法中。

    1、这里会先获取 RootBeanDefinition对象中的Class对象并确保已经关联了要创建的Bean的Class 。
    2、这里会检查3个条件

    (1)Bean的属性中的 beforeInstantiationResolved字段是否为true,默认是false。
    (2)Bean是原生的Bean
    (3)Bean的 hasInstantiationAwareBeanPostProcessors属性为true,这个属性在Spring准备刷新容器钱转杯BeanPostProcessors的时候会设置,如果当前Bean实现了 InstantiationAwareBeanPostProcessor则这个就会是true。

    当三个条件都存在的时候,就会调用实现的 InstantiationAwareBeanPostProcessor接口的 postProcessBeforeInstantiation方法,然后获取返回的Bean,如果返回的Bean不是null还会调用实现的 BeanPostProcessor接口的 postProcessAfterInitialization方法,这里用代码说明:

    1. protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
    2. Object bean = null;
    3. //条件1
    4. if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
    5. //条件2跟条件3
    6. if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
    7. Class targetType = determineTargetType(beanName, mbd);
    8. if (targetType != null) {
    9. //调用实现的postProcessBeforeInstantiation方法
    10. bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
    11. if (bean != null) {
    12. //调用实现的postProcessAfterInitialization方法
    13. bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
    14. }
    15. }
    16. }
    17. //不满足2或者3的时候就会设置为false
    18. mbd.beforeInstantiationResolved = (bean != null);
    19. }
    20. return bean;
    21. }

    3、如果上面3个条件其中一个不满足就不会调用实现的方法。默认这里都不会调用的这些 BeanPostProcessors的实现方法。然后继续执行后面的 doCreateBean方法。

    2.1 真正的创建Bean,doCreateBean

     

    doCreateBean方法逻辑

    这个代码的实现还是在 AbstractAutowireCapableBeanFactory方法中。流程是

    1、先检查 instanceWrapper变量是不是null,这里一般是null,除非当前正在创建的Bean在 factoryBeanInstanceCache中存在这个是保存还没创建完成的FactoryBean的集合。
    2、调用createBeanInstance方法实例化Bean,这个方法在后面会讲解
    3、如果当前 RootBeanDefinition对象还没有调用过实现了的 MergedBeanDefinitionPostProcessor接口的方法,则会进行调用 。
    4、 当满足以下三点
    (1)是单例Bean
    (2)尝试解析bean之间的循环引用
    (3)bean目前正在创建中
    则会进一步检查是否实现了 SmartInstantiationAwareBeanPostProcessor接口如果实现了则调用是实现的 getEarlyBeanReference方法 5、 调用 populateBean方法进行属性填充,这里后面会讲解 6、 调用 initializeBean方法对Bean进行初始化,这里后面会讲解

    2.1.1 实例化Bean,createBeanInstance

    实例化Bean

    这里的逻辑稍微有一点复杂,这个流程图已经是简化过后的了。简要根据代码说明一下流程:

    1. protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
    2. //步骤1
    3. Class beanClass = resolveBeanClass(mbd, beanName);
    4. if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {
    5. throw new BeanCreationException(mbd.getResourceDescription(), beanName,
    6. "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
    7. }
    8. //步骤2
    9. Supplier instanceSupplier = mbd.getInstanceSupplier();
    10. if (instanceSupplier != null) {
    11. return obtainFromSupplier(instanceSupplier, beanName);
    12. }
    13. //步骤3
    14. if (mbd.getFactoryMethodName() != null) {
    15. return instantiateUsingFactoryMethod(beanName, mbd, args);
    16. }
    17. boolean resolved = false;
    18. boolean autowireNecessary = false;
    19. if (args == null) {
    20. synchronized (mbd.constructorArgumentLock) {
    21. if (mbd.resolvedConstructorOrFactoryMethod != null) {
    22. resolved = true;
    23. autowireNecessary = mbd.constructorArgumentsResolved;
    24. }
    25. }
    26. }
    27. //步骤4.1
    28. if (resolved) {
    29. if (autowireNecessary) {
    30. return autowireConstructor(beanName, mbd, null, null);
    31. }
    32. else {
    33. return instantiateBean(beanName, mbd);
    34. }
    35. }
    36. //步骤4.2
    37. Constructor[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
    38. if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
    39. mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {
    40. return autowireConstructor(beanName, mbd, ctors, args);
    41. }
    42. //步骤5
    43. ctors = mbd.getPreferredConstructors();
    44. if (ctors != null) {
    45. return autowireConstructor(beanName, mbd, ctors, null);
    46. }
    47. return instantiateBean(beanName, mbd);
    48. }

    1、先检查Class是否已经关联了,并且对应的修饰符是否是public的
    2、如果用户定义了Bean实例化的函数,则调用并返回
    3、如果当前Bean实现了 FactoryBean接口则调用对应的 FactoryBean接口的 getObject方法
    4、根据getBean时候是否传入构造参数进行处理
    4.1 如果没有传入构造参数,则检查是否存在已经缓存的无参构造器,有则使用构造器直接创建,没有就会调用 instantiateBean方法先获取实例化的策略默认是 CglibSubclassingInstantiationStrategy,然后实例化Bean。最后返回
    4.2 如果传入了构造参数,则会先检查是否实现了 SmartInstantiationAwareBeanPostProcessor接口,如果实现了会调用 determineCandidateConstructors获取返回的候选构造器。
    4.3 检查4个条件是否满足一个
    (1)构造器不为null,
    (2)从RootBeanDefinition中获取到的关联的注入方式是构造器注入(没有构造参数就是setter注入,有则是构造器注入)
    (3)含有构造参数
    (4)getBean方法传入构造参数不是空

    满足其中一个则会调用返回的候选构造器实例化Bean并返回,如果都不满足,则会根据构造参数选则合适的有参构造器然后实例化Bean并返回

    5、如果上面都没有合适的构造器,则直接使用无参构造器创建并返回Bean。

    2.1.2 填充Bean,populateBean

    填充Bean

    这里还是根据代码来说一下流程:

     

    1、检查当前Bean是否实现了 InstantiationAwareBeanPostProcessorpostProcessAfterInstantiation方法则调用,并结束Bean的填充。
    2、将按照类型跟按照名称注入的Bean分开,如果注入的Bean还没有实例化的这里会实例化,然后放到 PropertyValues对象中。
    3、如果实现了 InstantiationAwareBeanPostProcessor类的 postProcessProperties则调用这个方法并获取返回值,如果返回值是null,则有可能是实现了过期的 postProcessPropertyValues方法,这里需要进一步调用 postProcessPropertyValues方法
    4、进行参数填充

    2.1.3 初始化Bean,initializeBean

     

    初始化Bean

    同时这里根据代码跟流程图来说明

    1、如果Bean实现了 BeanNameAware, BeanClassLoaderAware, BeanFactoryAware则调用对应实现的方法 。
    2、Bean不为null并且bean不是合成的,如果实现了 BeanPostProcessorpostProcessBeforeInitialization则会调用实现的 postProcessBeforeInitialization方法。在 ApplicationContextAwareProcessor类中实现了 postProcessBeforeInitialization方法。而这个类会在Spring刷新容器准备 beanFactory的时候会加进去,这里就会被调用,而调用里面会检查Bean是不是 EnvironmentAware, EmbeddedValueResolverAware, ResourceLoaderAware, ApplicationEventPublisherAware, MessageSourceAware, ApplicationContextAware的实现类。这里就会调用对应的实现方法。代码如下

    1. protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    2. .......
    3. beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
    4. .......
    1. public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
    2. if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
    3. bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
    4. bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){
    5. return bean;
    6. }
    7. AccessControlContext acc = null;
    8. if (System.getSecurityManager() != null) {
    9. acc = this.applicationContext.getBeanFactory().getAccessControlContext();
    10. }
    11. if (acc != null) {
    12. AccessController.doPrivileged((PrivilegedAction) () -> {
    13. invokeAwareInterfaces(bean);
    14. return null;
    15. }, acc);
    16. }
    17. else {
    18. invokeAwareInterfaces(bean);
    19. }
    20. return bean;
    21. }
    22. 1、实例化Bean然后,检查是否实现了 InitializingBeanafterPropertiesSet方法,如果实现了就会调用
      2、Bean不为null并且bean不是合成的,如果实现了 BeanPostProcessorpostProcessBeforeInitialization则会调用实现的 postProcessAfterInitialization方法。

      到此创建Bean 的流程就没了,剩下的就是容器销毁的时候的了

      三、destory方法跟销毁Bean

      Bean在创建完毕之后会检查用户是否指定了 destroyMethodName以及是否实现了 DestructionAwareBeanPostProcessor接口的 requiresDestruction方法,如果指定了会记录下来保存在 DisposableBeanAdapter对象中并保存在bean的 disposableBeans属性中。代码在 AbstractBeanFactoryregisterDisposableBeanIfNecessary

      1. protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
      2. ......
      3. registerDisposableBean(beanName,
      4. new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
      5. ......
      6. }
      1. public DisposableBeanAdapter(Object bean, String beanName, RootBeanDefinition beanDefinition,
      2. List postProcessors, @Nullable AccessControlContext acc) {
      3. .......
      4. String destroyMethodName = inferDestroyMethodIfNecessary(bean, beanDefinition);
      5. if (destroyMethodName != null && !(this.invokeDisposableBean && "destroy".equals(destroyMethodName)) &&
      6. !beanDefinition.isExternallyManagedDestroyMethod(destroyMethodName)) {
      7. ......
      8. this.destroyMethod = destroyMethod;
      9. }
      10. this.beanPostProcessors = filterPostProcessors(postProcessors, bean);
      11. }

      在销毁Bean的时候最后都会调用 AbstractAutowireCapableBeanFactorydestroyBean方法。

      1. public void destroyBean(Object existingBean) {
      2. new DisposableBeanAdapter(existingBean, getBeanPostProcessors(), getAccessControlContext()).destroy();
      3. }

      这里是创建一个 DisposableBeanAdapter对象,这个对象实现了Runnable接口,在实现的 run方法中会调用实现的 DisposableBean接口的 destroy方法。并且在创建 DisposableBeanAdapter对象的时候会根据传入的bean是否实现了 DisposableBean接口来设置 invokeDisposableBean变量,这个变量表实有没有实现 DisposableBean接口

      1. public DisposableBeanAdapter(Object bean, List postProcessors, AccessControlContext acc) {
      2. Assert.notNull(bean, "Disposable bean must not be null");
      3. this.bean = bean;
      4. this.beanName = bean.getClass().getName();
      5. //根据传入的bean是否实现了`DisposableBean`接口来设置`invokeDisposableBean`变量
      6. this.invokeDisposableBean = (this.bean instanceof DisposableBean);
      7. this.nonPublicAccessAllowed = true;
      8. this.acc = acc;
      9. this.beanPostProcessors = filterPostProcessors(postProcessors, bean);
      10. }
      11. public void destroy() {
      12. ......
      13. //根据invokeDisposableBean决定是否调用destroy方法
      14. if (this.invokeDisposableBean) {
      15. if (logger.isTraceEnabled()) {
      16. logger.trace("Invoking destroy() on bean with name '" + this.beanName + "'");
      17. }
      18. try {
      19. if (System.getSecurityManager() != null) {
      20. AccessController.doPrivileged((PrivilegedExceptionAction) () -> {
      21. ((DisposableBean) this.bean).destroy();
      22. return null;
      23. }, this.acc);
      24. }
      25. else {
      26. ((DisposableBean) this.bean).destroy();
      27. }
      28. }
      29. catch (Throwable ex) {
      30. String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
      31. if (logger.isDebugEnabled()) {
      32. logger.warn(msg, ex);
      33. }
      34. else {
      35. logger.warn(msg + ": " + ex);
      36. }
      37. }
      38. }
      39. ......
      40. }
      41. 四、总结

        最后来一个大的流程

         实例化前的准备阶

         

         实例化前

         

        实例化后

         

        初始化前

         

         

         只有当你开始,你才会到达你的理想和目的地,只有当你努力,
        你才会获得辉煌的成功,只有当你播种,你才会有所收获。只有追求,
        才能尝到成功的味道,坚持在昨天叫立足,坚持在今天叫进取,坚持在明天叫成功。欢迎所有小伙伴们点赞+收藏!!!

        相信通过本文的学习,你应该会对 Spring Bean 生命周期有一个更加全面的认识。

        都看到这里了,就点个👍 👍 👍 吧。

      42. 相关阅读:
        提升网络速度的几种有效方法
        Vue项目保持用户登录状态(localStorage + vuex 刷新页面后状态依然保持)
        RabbitMQ学习笔记
        Stimulsoft Ultimate 2022.4.5 Crack
        es(Elasticsearch)客户端Kibana安装使用(03Kibana安装篇)
        苍穹外卖(七) Spring Task 完成订单状态定时处理
        《JAVA程序设计》教学上机实验报告
        ssh秘钥和python 虚拟环境
        用patchelf改程序后在exp中用gdb.attach()调试堆栈
        Oracle/PLSQL: Avg Function
      43. 原文地址:https://blog.csdn.net/weixin_48321993/article/details/125978681