关于java:11张图和源码带你解析Spring-Bean的生命周期建议收藏

30次阅读

共计 11093 个字符,预计需要花费 28 分钟才能阅读完成。

在网上曾经有跟多 Bean 的生命周期的博客,然而很多都是基于比拟老的版本了,最近把整个流程画成了一个流程图。待会儿应用流程图,阐明以及代码的模式来阐明整个申明周期的流程。留神因为代码比拟多,这里的流程图只画出了大略的流程,具体的能够深刻代码

1. 获取 Bean

这里的流程图的入口在 AbstractBeanFactory 类的 doGetBean 办法,这里能够配合后面的 getBean 办法剖析文章进行浏览。次要流程就是

  1. 先解决 Bean 的名称,因为如果以“&”结尾的 Bean 名称示意获取的是对应的 FactoryBean 对象;
  2. 从缓存中获取单例 Bean,有则进一步判断这个 Bean 是不是在创立中,如果是的就期待创立结束,否则间接返回这个 Bean 对象
  3. 如果不存在单例 Bean 缓存,则先进行循环依赖的解析
  4. 解析结束之后先获取父类 BeanFactory,获取到了则调用父类的 getBean 办法,不存在则先合并而后创立 Bean

2. 创立 Bean

2.1 创立 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 办法,这里用代码阐明

protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
        Object bean = null;
              // 条件 1
        if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
          // 条件 2 跟条件 3
            if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {Class<?> targetType = determineTargetType(beanName, mbd);
                if (targetType != null) {
 // 调用实现的 postProcessBeforeInstantiation 办法
                    bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                    if (bean != null) {
// 调用实现的 postProcessAfterInitialization 办法
                        bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                    }
                }
            }
                  // 不满足 2 或者 3 的时候就会设置为 false
            mbd.beforeInstantiationResolved = (bean != null);
        }
        return bean;
    }
  1. 如果下面 3 个条件其中一个不满足就不会调用实现的办法。默认这里都不会调用的这些 BeanPostProcessors 的实现办法。而后继续执行前面的 doCreateBean 办法。

2.1 真正的创立 Bean,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

这里的逻辑略微有一点简单,这个流程图曾经是简化过后的了。简要依据代码阐明一下流程

 protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
        // 步骤 1
        Class<?> beanClass = resolveBeanClass(mbd, beanName);

        if (beanClass != null && !Modifier.isPublic(beanClass.getModifiers()) && !mbd.isNonPublicAccessAllowed()) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,
                    "Bean class isn't public, and non-public access not allowed: " + beanClass.getName());
        }
        // 步骤 2
        Supplier<?> instanceSupplier = mbd.getInstanceSupplier();
        if (instanceSupplier != null) {return obtainFromSupplier(instanceSupplier, beanName);
        }
        // 步骤 3
        if (mbd.getFactoryMethodName() != null) {return instantiateUsingFactoryMethod(beanName, mbd, args);
        }


        boolean resolved = false;
        boolean autowireNecessary = false;
        if (args == null) {synchronized (mbd.constructorArgumentLock) {if (mbd.resolvedConstructorOrFactoryMethod != null) {
                    resolved = true;
                    autowireNecessary = mbd.constructorArgumentsResolved;
                }
            }
        }
        // 步骤 4.1
        if (resolved) {if (autowireNecessary) {return autowireConstructor(beanName, mbd, null, null);
            }
            else {return instantiateBean(beanName, mbd);
            }
        }

          // 步骤 4.2
        Constructor<?>[] ctors = determineConstructorsFromBeanPostProcessors(beanClass, beanName);
        if (ctors != null || mbd.getResolvedAutowireMode() == AUTOWIRE_CONSTRUCTOR ||
                mbd.hasConstructorArgumentValues() || !ObjectUtils.isEmpty(args)) {return autowireConstructor(beanName, mbd, ctors, args);
        }

        // 步骤 5
        ctors = mbd.getPreferredConstructors();
        if (ctors != null) {return autowireConstructor(beanName, mbd, ctors, null);
        }

        
        return instantiateBean(beanName, mbd);
    }
  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

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

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {if (bw == null) {if (mbd.hasPropertyValues()) {
                throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Cannot apply property values to null instance");
            }
            else {
                // Skip property population phase for null instance.
                return;
            }
        }


        boolean continueWithPropertyPopulation = true;
        // 步骤 1
        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                        continueWithPropertyPopulation = false;
                        break;
                    }
                }
            }
        }

        if (!continueWithPropertyPopulation) {return;}
// 步骤 2 --------------------
        PropertyValues pvs = (mbd.hasPropertyValues() ? mbd.getPropertyValues() : null);

        int resolvedAutowireMode = mbd.getResolvedAutowireMode();
        if (resolvedAutowireMode == AUTOWIRE_BY_NAME || resolvedAutowireMode == AUTOWIRE_BY_TYPE) {MutablePropertyValues newPvs = new MutablePropertyValues(pvs);
            // Add property values based on autowire by name if applicable.
            if (resolvedAutowireMode == AUTOWIRE_BY_NAME) {autowireByName(beanName, mbd, bw, newPvs);
            }
            // Add property values based on autowire by type if applicable.
            if (resolvedAutowireMode == AUTOWIRE_BY_TYPE) {autowireByType(beanName, mbd, bw, newPvs);
            }
            pvs = newPvs;
        }

        boolean hasInstAwareBpps = hasInstantiationAwareBeanPostProcessors();
        boolean needsDepCheck = (mbd.getDependencyCheck() != AbstractBeanDefinition.DEPENDENCY_CHECK_NONE);

        PropertyDescriptor[] filteredPds = null;
// 步骤 3
        if (hasInstAwareBpps) {if (pvs == null) {pvs = mbd.getPropertyValues();
            }
            for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                    PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);
                    if (pvsToUse == null) {if (filteredPds == null) {filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
                        }
                        pvsToUse = ibp.postProcessPropertyValues(pvs, filteredPds, bw.getWrappedInstance(), beanName);
                        if (pvsToUse == null) {return;}
                    }
                    pvs = pvsToUse;
                }
            }
        }
        if (needsDepCheck) {if (filteredPds == null) {filteredPds = filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);
            }
            checkDependencies(beanName, mbd, filteredPds, pvs);
        }
// 步骤 4
        if (pvs != null) {applyPropertyValues(beanName, mbd, bw, pvs);
        }
    }
  1. 查看以后 Bean 是否实现了 InstantiationAwareBeanPostProcessor 的 postProcessAfterInstantiation 办法则调用,并完结 Bean 的填充。
  2. 将依照类型跟依照名称注入的 Bean 离开,如果注入的 Bean 还没有实例化的这里会实例化,而后放到 PropertyValues 对象中。
  3. 如果实现了 InstantiationAwareBeanPostProcessor 类的 postProcessProperties 则调用这个办法并获取返回值,如果返回值是 null,则有可能是实现了过期的 postProcessPropertyValues 办法,这里须要进一步调用 postProcessPropertyValues 办法
  4. 进行参数填充

2.1.3 初始化 Bean,initializeBean

同时这里依据代码跟流程图来阐明

  1. 如果 Bean 实现了 BeanNameAware,BeanClassLoaderAware,BeanFactoryAware 则调用对应实现的办法
  2. Bean 不为 null 并且 bean 不是合成的,如果实现了 BeanPostProcessor 的 postProcessBeforeInitialization 则会调用实现的 postProcessBeforeInitialization 办法。在 ApplicationContextAwareProcessor 类中实现了 postProcessBeforeInitialization 办法。而这个类会在 Spring 刷新容器筹备 beanFactory 的时候会加进去,这里就会被调用,而调用外面会查看 Bean 是不是 EnvironmentAware,EmbeddedValueResolverAware,ResourceLoaderAware,ApplicationEventPublisherAware,MessageSourceAware,ApplicationContextAware 的实现类。这里就会调用对应的实现办法。代码如下
    protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
        .......
        beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
        .......
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
                bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
                bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){return bean;}

        AccessControlContext acc = null;

        if (System.getSecurityManager() != null) {acc = this.applicationContext.getBeanFactory().getAccessControlContext();}

        if (acc != null) {AccessController.doPrivileged((PrivilegedAction<Object>) () -> {invokeAwareInterfaces(bean);
                return null;
            }, acc);
        }
        else {invokeAwareInterfaces(bean);
        }

        return bean;
    }

3. 实例化 Bean 而后,查看是否实现了 InitializingBean 的 afterPropertiesSet 办法,如果实现了就会调用
4.Bean 不为 null 并且 bean 不是合成的,如果实现了 BeanPostProcessor 的 postProcessBeforeInitialization 则会调用实现的 postProcessAfterInitialization 办法。到此创立 Bean 的流程就没了,剩下的就是容器销毁的时候的了

3.destory 办法跟销毁 Bean

Bean 在创立结束之后会检查用户是否指定了 destroyMethodName 以及是否实现了 DestructionAwareBeanPostProcessor 接口的 requiresDestruction 办法,如果指定了会记录下来保留在 DisposableBeanAdapter 对象中并保留在 bean 的 disposableBeans 属性中。代码在 AbstractBeanFactory 的 registerDisposableBeanIfNecessary 中

    protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
          ......
                registerDisposableBean(beanName,
                        new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
            ......
    }
public DisposableBeanAdapter(Object bean, String beanName, RootBeanDefinition beanDefinition,
            List<BeanPostProcessor> postProcessors, @Nullable AccessControlContext acc) {
          .......
        String destroyMethodName = inferDestroyMethodIfNecessary(bean, beanDefinition);
        if (destroyMethodName != null && !(this.invokeDisposableBean && "destroy".equals(destroyMethodName)) &&
                !beanDefinition.isExternallyManagedDestroyMethod(destroyMethodName)) {
            ......
            this.destroyMethod = destroyMethod;
        }
        this.beanPostProcessors = filterPostProcessors(postProcessors, bean);
    }

在销毁 Bean 的时候最初都会调用 AbstractAutowireCapableBeanFactory 的 destroyBean 办法。

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

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

    public DisposableBeanAdapter(Object bean, List<BeanPostProcessor> postProcessors, AccessControlContext acc) {Assert.notNull(bean, "Disposable bean must not be null");
        this.bean = bean;
        this.beanName = bean.getClass().getName();
          // 依据传入的 bean 是否实现了 `DisposableBean` 接口来设置 `invokeDisposableBean` 变量
        this.invokeDisposableBean = (this.bean instanceof DisposableBean);
        this.nonPublicAccessAllowed = true;
        this.acc = acc;
        this.beanPostProcessors = filterPostProcessors(postProcessors, bean);
    }

    public void destroy() {
        ......
  // 依据 invokeDisposableBean 决定是否调用 destroy 办法
        if (this.invokeDisposableBean) {if (logger.isTraceEnabled()) {logger.trace("Invoking destroy() on bean with name'" + this.beanName + "'");
            }
            try {if (System.getSecurityManager() != null) {AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {((DisposableBean) this.bean).destroy();
                        return null;
                    }, this.acc);
                }
                else {((DisposableBean) this.bean).destroy();}
            }
            catch (Throwable ex) {
                String msg = "Invocation of destroy method failed on bean with name'" + this.beanName + "'";
                if (logger.isDebugEnabled()) {logger.warn(msg, ex);
                }
                else {logger.warn(msg + ":" + ex);
                }
            }
        }
......
    }

4. 总结

最初来一个大的流程

  • 实例化前的筹备阶段

  • 实例化前

  • 实例化后

  • 初始化前

  • 初始化之后 + 销毁

写在最初

欢送大家关注我的公众号【 惊涛骇浪如码 】,海量 Java 相干文章,学习材料都会在外面更新,整顿的材料也会放在外面。

感觉写的还不错的就点个赞,加个关注呗!点关注,不迷路,继续更新!!!

正文完
 0