之前简略记录了下springBean的生命周期,最近打开来看了下,发现自己脱漏了很多细节,很多点都连接不上
明天从新翻看《spring揭秘》,查资料,补了许多细节。心愿可能让本人和大家更容易看懂吧

Bean的生命周期的齐全实现须要两个阶段

  1. 容器的启动
  2. bean的实例化过程(涵盖了bean生命周期的大部分)

容器启动阶段

  1. 重点是收集到元信息配置信息,即创立bean须要的信息(beanDefinition)
    通过BeanDefinitionReader,读取到beanDefinition信息,再通过beanDefinitionRegistry,将BeanDefinition注册到其外面
// 这是 PropertiesBeanDefinitionReader 把从properties文件读取到的配置信息,// 通过 BeanDefinitionRegistry 注册 BeanDefinition的过程            AbstractBeanDefinition bd = BeanDefinitionReaderUtils.createBeanDefinition(                    parent, className, getBeanClassLoader());            bd.setScope(scope); // 作用域 默认singleton            bd.setAbstract(isAbstract); // 是否是形象 默认false 如果是形象的,容器不会实例化bean,而是将beanDefinition信息作为其子类应用            bd.setLazyInit(lazyInit); // 懒加载 默认false 如果是false,容器一启动就会加载bean            bd.setConstructorArgumentValues(cas); // 结构参数            bd.setPropertyValues(pvs); // 属性信息            getRegistry().registerBeanDefinition(beanName, bd); // 注册Beandefinition

BeanDefinitionReader 有多种,包含:

  • PropertiesBeanDefinitionReader 读取Properties配置文件
  • GroovyBeanDefinitionReader 读取Groovy配置文件
  • XmlBeanDefinitionReader 读取Xml配置文件

bean实例化前 对beanDefinition做出自定义批改

BeanFactoryPostProcessor实例化bean之前,能够容许批改beanDefinition信息,上面是spring默认实现的BeanFactoryPostProcessor类:

  • PropertyPlaceholderConfigurer容许咱们在XML配置文件中应用占位符(PlaceHolder),并将这些占位符所代表的资源独自配置到简略的properties文件中来加载
  • PropertyOverrideConfigurer笼罩对象的属性值
  • 咱们能够本人实现BeanFactoryPostProcessor依赖注入beanFactory ,批改beanDefinition信息

bean实例化阶段

doCreateBean源码办法(上面仅对beanFactory容器做解析,applicationContext容器其实大同小异)

/**     * Actually create the specified bean. Pre-creation processing has already happened     * at this point, e.g. checking {@code postProcessBeforeInstantiation} callbacks.     * <p>Differentiates between default bean instantiation, use of a     * factory method, and autowiring a constructor.     * @param beanName the name of the bean     * @param mbd the merged bean definition for the bean     * @param args explicit arguments to use for constructor or factory method invocation     * @return a new instance of the bean     * @throws BeanCreationException if the bean could not be created     * @see #instantiateBean     * @see #instantiateUsingFactoryMethod     * @see #autowireConstructor     */    protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)            throws BeanCreationException {        // Instantiate the bean.        BeanWrapper instanceWrapper = null;        if (mbd.isSingleton()) {            instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);        }        if (instanceWrapper == null) {            instanceWrapper = createBeanInstance(beanName, mbd, args);        }        // 实例化bean        Object bean = instanceWrapper.getWrappedInstance();        Class<?> beanType = instanceWrapper.getWrappedClass();        if (beanType != NullBean.class) {            mbd.resolvedTargetType = beanType;        }        // Allow post-processors to modify the merged bean definition.        synchronized (mbd.postProcessingLock) {            if (!mbd.postProcessed) {                try {                    applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);                }                catch (Throwable ex) {                    throw new BeanCreationException(mbd.getResourceDescription(), beanName,                            "Post-processing of merged bean definition failed", ex);                }                mbd.postProcessed = true;            }        }        // Eagerly cache singletons to be able to resolve circular references        // even when triggered by lifecycle interfaces like BeanFactoryAware.        boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&                isSingletonCurrentlyInCreation(beanName));        if (earlySingletonExposure) {            if (logger.isTraceEnabled()) {                logger.trace("Eagerly caching bean '" + beanName +                        "' to allow for resolving potential circular references");            }            addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));        }        // Initialize the bean instance.              Object exposedObject = bean;        try {                        // 填充bean对象属性            populateBean(beanName, mbd, instanceWrapper);                        //  初始化bean            exposedObject = initializeBean(beanName, exposedObject, mbd);        }        catch (Throwable ex) {            if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {                throw (BeanCreationException) ex;            }            else {                throw new BeanCreationException(                        mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);            }        }        if (earlySingletonExposure) {            Object earlySingletonReference = getSingleton(beanName, false);            if (earlySingletonReference != null) {                if (exposedObject == bean) {                    exposedObject = earlySingletonReference;                }                else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {                    String[] dependentBeans = getDependentBeans(beanName);                    Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);                    for (String dependentBean : dependentBeans) {                        if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {                            actualDependentBeans.add(dependentBean);                        }                    }                    if (!actualDependentBeans.isEmpty()) {                        throw new BeanCurrentlyInCreationException(beanName,                                "Bean with name '" + beanName + "' has been injected into other beans [" +                                StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +                                "] in its raw version as part of a circular reference, but has eventually been " +                                "wrapped. This means that said other beans do not use the final version of the " +                                "bean. This is often the result of over-eager type matching - consider using " +                                "'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");                    }                }            }        }        // Register bean as disposable.        try {            // 查看是否实现DisposableBean接口,有的话注册销毁回调办法            registerDisposableBeanIfNecessary(beanName, bean, mbd);        }        catch (BeanDefinitionValidationException ex) {            throw new BeanCreationException(                    mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);        }        return exposedObject;    }
  1. 首先第一步,调用createBeanInstance办法,利用反射调用类的构造方法,实例化bean,返回beanWrapper对象,再调用getWrappedInstance办法失去实例化的bean,beanWrapper对象具备获取对象属性的性能,所以能够调用populateBean用来实现属性填充。

  1. 开始实例化bean之前,会查看bean有没有实现过Aware接口,如果有则实现。

    // AbstractAutowireCapableBeanFactory类中的 initializeBean办法private void invokeAwareMethods(String beanName, Object bean) {     if (bean instanceof Aware) {         // 如果Spring容器检测到以后对象实例实现了该接口,会将该对象实例的bean定义对应的beanName设置到以后对象实例。         if (bean instanceof BeanNameAware) {             ((BeanNameAware) bean).setBeanName(beanName);         }         // 如果容器检测到以后对象实例实现了该接口,会将对应加载以后bean的Classloader注入以后对象实例。         // 默认会应用加载org.springframework.util.ClassUtils类的Classloader         if (bean instanceof BeanClassLoaderAware) {             ClassLoader bcl = getBeanClassLoader();             if (bcl != null) {                 ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);             }         }         if (bean instanceof BeanFactoryAware) {             ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);         }         // 以上几个Aware接口只是针对BeanFactory类型的容器而言     } }
对于ApplicationContext类型容器,会额定实现几个Aware接口
  1. BeanPostProcessor阶段
BeanPostProcessor的概念容易与BeanFactoryPostProcessor的概念混同。
但只有记住BeanPostProcessor是存在于对象实例化阶段,而BeanFactoryPostProcessor则是存在于容器启动阶段,这两个概念就比拟容易辨别了。

BeanPostProcessor 有两个须要子类实现的办法

public interface BeanPostProcessor {    /**     * 调用bean的init办法之前做的前置解决     */    @Nullable    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {        return bean;    }    /**     * 调用bean的init办法之后做的前置解决     */    @Nullable    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {        return bean;    }}

在initializeBean办法内能够看到BeanPostProcessor的调用程序

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 {            // 调用实现了Aware接口的对象办法            invokeAwareMethods(beanName, bean);        }        Object wrappedBean = bean;        if (mbd == null || !mbd.isSynthetic()) {            // BeanPostProcessor前置解决            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);        }        try {            // 调用bean的init办法            invokeInitMethods(beanName, wrappedBean, mbd);        }        catch (Throwable ex) {            throw new BeanCreationException(                    (mbd != null ? mbd.getResourceDescription() : null),                    beanName, "Invocation of init method failed", ex);        }        if (mbd == null || !mbd.isSynthetic()) {            // BeanPostProcessor后置解决            wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);        }        return wrappedBean;    }
留神:applcationContext容器中实现BeanPostProcessor接口的postProcessBeforeInitialization中,会对实现了Aware接口的bean进行invoke调用。
这里和BeanFactory有些不同,BeanFactory是在BeanPostProcessor之前实现的
  1. InitializingBean和init-method

这两个办法都是在invokeInitMethods办法里调用,
InitializingBean接口须要实现afterPropertiesSet 办法容许bean实例在设置完所有bean属性后执行其整体配置验证和最终初始化。
init-method, 对于用户来说能够自定义办法的名称,也能够对立设置所有对象的initMethod比拟灵便,防止批改代码,耦合性低。

  1. DisposableBean与destroy-method

DisposableBean接口,子类须要实现destroy办法,来销毁对象,只实用于单例对象,不是单例的话,须要交给调用者本人销毁。
destroy-method注册销毁函数,作用和destroy办法同理

总结

本文次要讲了bean在BeanFacotry容器的生命周期,applicationContext容器略微提了几点不同,applicationContext容器减少更多的个性,像事件公布监听,国际化信息反对等。
bean的生命周期次要波及到容器的加载和bean的实例化。

容器的加载:

  • 加载资源文件到beanDefinition(元信息)
  • 调用实现了BeanFactoryPostProcessor接口的办法,能够对beanDefinition进行批改。

bean的实例化:

  • 利用反射+beanDefinition元信息实例化失去对象
  • populateBean办法填充属性
  • 测验对象是否实现过Aware接口,有则调用其实现
  • 如果对象有实现BeanPostProcessor接口,须要先实现前置办法
  • 调用InitializingBean和init-method办法 如果有实现或标记的话
  • 再调用BeanPostProcessor接口的后置办法
  • 最初查看对象是否实现 DisposableBean与destroy-method 来销毁bean(DisposableBean接口只针对单例bean)

材料:

《spring揭秘》王福强

本文由mdnice多平台公布