Spring中Bean的生命周期

147 阅读12分钟

阶段一:Bean元信息的配置阶段

该阶段就是用户对Bean信息的定义阶段。通过xml、注解、properties文件(一般不用)来定义Bean信息,或者使用API的方式即使用BeanDefinitionBuilder类直接构建BeanDefinition对象以定义Bean信息。BeanDefinition是表示Bean定义信息的接口,里面定义了一些获取bean定义配置信息的各种方法。不管用户以何种方式定义Bean,在后续阶段中都会将定义好的Bean信息组装成BeanDefinition并注册到容器中。

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {

    /**
     * 设置此bean的父bean名称(对应xml中bean元素的parent属性)
     */
    void setParentName(@Nullable String parentName);

    /**
     * 返回此bean定义时指定的父bean的名称
     */
    @Nullable
    String getParentName();

    /**
     * 指定此bean定义的bean类名(对应xml中bean元素的class属性)
     */
    void setBeanClassName(@Nullable String beanClassName);

    /**
     * 返回此bean定义的当前bean类名
     * 注意,如果子定义重写/继承其父类的类名,则这不一定是运行时使用的实际类名。此外,这可能只是调用工厂方法的类,或者在调用方法的工厂bean引用的情况下,它甚至可能是空的。因此,不要认为这是运行时的最终bean类型,而只将其用于单个bean定义级别的解析目的。
     */
    @Nullable
    String getBeanClassName();

    /**
     * 设置此bean的生命周期,如:singleton、prototype(对应xml中bean元素的scope属性)
     */
    void setScope(@Nullable String scope);

    /**
     * 返回此bean的生命周期,如:singleton、prototype
     */
    @Nullable
    String getScope();

    /**
     * 设置是否应延迟初始化此bean(对应xml中bean元素的lazy属性)
     */
    void setLazyInit(boolean lazyInit);

    /**
     * 返回是否应延迟初始化此bean,只对单例bean有效
     */
    boolean isLazyInit();

    /**
     * 设置此bean依赖于初始化的bean的名称,bean工厂将保证dependsOn指定的bean会在当前bean初始化之前先初始化好
     */
    void setDependsOn(@Nullable String... dependsOn);

    /**
     * 返回此bean所依赖的bean名称
     */
    @Nullable
    String[] getDependsOn();

    /**
     * 设置此bean是否作为其他bean自动注入时的候选者
     * autowireCandidate
     */
    void setAutowireCandidate(boolean autowireCandidate);

    /**
     * 返回此bean是否作为其他bean自动注入时的候选者
     */
    boolean isAutowireCandidate();

    /**
     * 设置此bean是否为自动注入的主要候选者
     * primary:是否为主要候选者
     */
    void setPrimary(boolean primary);

    /**
     * 返回此bean是否作为自动注入的主要候选者
     */
    boolean isPrimary();

    /**
     * 指定要使用的工厂bean(如果有)。这是要对其调用指定工厂方法的bean的名称。
     * factoryBeanName:工厂bean名称
     */
    void setFactoryBeanName(@Nullable String factoryBeanName);

    /**
     * 返回工厂bean名称(如果有)(对应xml中bean元素的factory-bean属性)
     */
    @Nullable
    String getFactoryBeanName();

    /**
     * 指定工厂方法(如果有)。此方法将使用构造函数参数调用,如果未指定任何参数,则不使用任何参数调用。该方法将在指定的工厂bean(如果有的话)上调用,或者作为本地bean类上的静态方法调用。
     * factoryMethodName:工厂方法名称
     */
    void setFactoryMethodName(@Nullable String factoryMethodName);

    /**
     * 返回工厂方法名称(对应xml中bean的factory-method属性)
     */
    @Nullable
    String getFactoryMethodName();

    /**
     * 返回此bean的构造函数参数值
     */
    ConstructorArgumentValues getConstructorArgumentValues();

    /**
     * 是否有构造器参数值设置信息(对应xml中bean元素的<constructor-arg />子元素)
     */
    default boolean hasConstructorArgumentValues() {
        return !getConstructorArgumentValues().isEmpty();
    }

    /**
     * 获取bean定义是配置的属性值设置信息
     */
    MutablePropertyValues getPropertyValues();

    /**
     * 这个bean定义中是否有属性设置信息(对应xml中bean元素的<property />子元素)
     */
    default boolean hasPropertyValues() {
        return !getPropertyValues().isEmpty();
    }

    /**
     * 设置bean初始化方法名称
     */
    void setInitMethodName(@Nullable String initMethodName);

    /**
     * bean初始化方法名称
     */
    @Nullable
    String getInitMethodName();

    /**
     * 设置bean销毁方法的名称
     */
    void setDestroyMethodName(@Nullable String destroyMethodName);

    /**
     * bean销毁的方法名称
     */
    @Nullable
    String getDestroyMethodName();

    /**
     * 设置bean的role信息
     */
    void setRole(int role);

    /**
     * bean定义的role信息
     */
    int getRole();

    /**
     * 设置bean描述信息
     */
    void setDescription(@Nullable String description);

    /**
     * bean描述信息
     */
    @Nullable
    String getDescription();

    /**
     * bean类型解析器
     */
    ResolvableType getResolvableType();

    /**
     * 是否是单例的bean
     */
    boolean isSingleton();

    /**
     * 是否是多列的bean
     */
    boolean isPrototype();

    /**
     * 对应xml中bean元素的abstract属性,用来指定是否是抽象的
     */
    boolean isAbstract();

    /**
     * 返回此bean定义来自的资源的描述(以便在出现错误时显示上下文)
     */
    @Nullable
    String getResourceDescription();

    @Nullable
    BeanDefinition getOriginatingBeanDefinition();

}

阶段二:Bean元信息的解析阶段

通过XmlBeanDefinitionReader、PropertiesBeanDefinitionReader、AnnotatedBeanDefinitionReader将阶段一中各种方式定义好的bean配置信息解析为BeanDefinition对象。

阶段三:Spring Bean注册阶段

通过BeanDefinitionRegistry接口来注册Bean。

public interface BeanDefinitionRegistry extends AliasRegistry {

    /**
     * 注册一个新的bean定义
     * beanName:bean的名称
     * beanDefinition:bean定义信息
     */
    void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
            throws BeanDefinitionStoreException;

    /**
     * 通过bean名称移除已注册的bean
     * beanName:bean名称
     */
    void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

    /**
     * 通过名称获取bean的定义信息
     * beanName:bean名称
     */
    BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

    /**
     * 查看beanName是否注册过
     */
    boolean containsBeanDefinition(String beanName);

    /**
     * 获取已经定义(注册)的bean名称列表
     */
    String[] getBeanDefinitionNames();

    /**
     * 返回注册器中已注册的bean数量
     */
    int getBeanDefinitionCount();

    /**
     * 确定给定的bean名称或者别名是否已在此注册表中使用
     * beanName:可以是bean名称或者bean的别名
     */
    boolean isBeanNameInUse(String beanName);

}

BeanDefinitionRegistry接口继承了AliasRegistry接口,这个接口中定义了操作bean别名的一些方法

public interface AliasRegistry {

    /**
     * 给name指定别名alias
     */
    void registerAlias(String name, String alias);

    /**
     * 从此注册表中删除指定的别名
     */
    void removeAlias(String alias);

    /**
     * 判断name是否作为别名已经被使用了
     */
    boolean isAlias(String name);

    /**
     * 返回name对应的所有别名
     */
    String[] getAliases(String name);

}

DefaultListableBeanFactory是BeanDefinitionRegistry接口的唯一实现类。

阶段四:BeanDefinition合并阶段

当定义Bean的时候包含父子Bean关系,子Bean的定义信息是不完全的,有一部分定义信息是继承自父Bean,因此需要合并父子BeanDefinition,最终得到一个RootBeanDefinition,其包含了bean定义的所有信息,包含了从父bean中继继承过来的所有信息,后续bean的所有创建工作就是依靠合并之后BeanDefinition来进行。 BeanDefinition的合并使用的是此方法: org.springframework.beans.factory.support.AbstractBeanFactory#getMergedBeanDefinition

需要注意的是,Bean的定义可能存在多级父子关系,合并的时候进进行递归合并,最终得到一个包含完整信息的RootBeanDefinition

阶段五:Bean的Class加载阶段

这个阶段就是将bean的class名称转换为Class类型的对象。 当BeanDefinition对象中的beanClass属性值是该类的全限定名时,使用类加载器加载全限定名得到该类的字节码对象。

该阶段使用的是如下方法: org.springframework.beans.factory.support.AbstractBeanFactory#resolveBeanClass

阶段六:Bean实例化阶段

该阶段分为两小阶段:Bean实例化前操作和Bean实例化操作 DefaultListableBeanFactory类中有个重要字段 private final List<BeanPostProcessor> beanPostProcessors = new CopyOnWriteArrayList<>();,该字段是BeanPostProcess类的集合。BeanPostProcessor接口及其子接口提供了对Spring生命周期中扩展点的处理,bean生命周期中的所有扩展点都是依靠这个集合中的BeanPostProcessor来实现的。

实例化前

在Bean实例化之前会调用applyBeanPostProcessorsBeforeInstantiation方法:

@Nullable
    protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);
                if (result != null) {
                    return result;
                }
            }
        }
        return null;
    }

该方法为开发者提供了实例化前的扩展点,开发者自己可以在这个地方直接去创建一个对象作为bean实例,而跳过spring内部实例化bean的过程。

上面代码中轮询beanPostProcessors列表,如果类型是InstantiationAwareBeanPostProcessor, 尝试调用InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation获取bean的实例对象,如果能够获取到,那么将返回值作为当前bean的实例,那么spring自带的实例化bean的过程就被跳过了。

postProcessBeforeInstantiation方法如下:

default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
    return null;
}

Bean的实例化阶段

该阶段通过反射调用类的构造器实例化Bean。Spring提供了接口允许开发者自己判断具体调用哪个构造器。

for (BeanPostProcessor bp : getBeanPostProcessors()) {
    if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
        SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
        Constructor<?>[] ctors = ibp.determineCandidateConstructors(beanClass, beanName);
        if (ctors != null) {
            return ctors;
        }
    }
}

会调用SmartInstantiationAwareBeanPostProcessor接口的determineCandidateConstructors方法,这个方法会返回候选的构造器列表,也可以返回空,看一下这个方法的源码:

@Nullable
default Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName)
throws BeansException {

    return null;
}

阶段七:合并后的BeanDefinition处理

protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof MergedBeanDefinitionPostProcessor) {
                MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
                bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
            }
        }
    }

pring会轮询BeanPostProcessor,依次调用MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition

void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);

第一个参数为beanDefinition,表示合并之后的RootBeanDefinition,我们可以在这个方法内部对合并之后的BeanDefinition进行再次处理。

MergedBeanDefinitionPostProcessor有2个实现类:

org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
在 postProcessMergedBeanDefinition 方法中对 @Autowired@Value 标注的方法、字段进行缓存

org.springframework.context.annotation.CommonAnnotationBeanPostProcessor
在 postProcessMergedBeanDefinition 方法中对 @Resource 标注的字段、@Resource 标注的方法、 @PostConstruct 标注的字段、 @PreDestroy标注的方法进行缓存

阶段八:Bean的属性设置阶段

该阶段分为三个小阶段:实例化后阶段、Bean属性赋值前处理阶段、Bean属性赋值阶段

实例化后阶段

调用InstantiationAwareBeanPostProcessor接口的postProcessAfterInstantiation这个方法。

for (BeanPostProcessor bp : getBeanPostProcessors()) {
    if (bp instanceof InstantiationAwareBeanPostProcessor) {
        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
        if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
            return;
        }
    }
}
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
    return true;
}

postProcessAfterInstantiation方法返回false的时候,后续的Bean属性赋值前处理、Bean属性赋值都会被跳过。

Bean属性赋值前处理阶段

这个阶段会调用InstantiationAwareBeanPostProcessor接口的postProcessProperties方法

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;
    }
}
@Nullable
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
    throws BeansException {

    return null;
}

从上面可以看出,如果InstantiationAwareBeanPostProcessor中的postProcessPropertiespostProcessPropertyValues都返回空的时候,表示这个bean不需要设置属性,直接返回了,直接进入下一个阶段。PropertyValues中保存了bean实例对象中所有属性值的设置,所以我们可以在这个这个方法中对PropertyValues值进行修改。

Bean属性赋值阶段

循环处理PropertyValues中的属性值信息,通过反射调用set方法将属性的值设置到bean实例中。PropertyValues中的值是通过bean xml中property元素配置的,或者调用MutablePropertyValues中add方法设置的值。

阶段九:Bean初始化阶段

该阶段分为五个小阶段:

  • Bean Aware接口回调
  • Bean初始化前操作
  • Bean初始化操作
  • Bean初始化后操作
  • Bean初始化完成操作

Bean Aware 接口回调

private void invokeAwareMethods(final String beanName, final Object bean) {
        if (bean instanceof Aware) {
            if (bean instanceof BeanNameAware) {
                ((BeanNameAware) bean).setBeanName(beanName);
            }
            if (bean instanceof BeanClassLoaderAware) {
                ClassLoader bcl = getBeanClassLoader();
                if (bcl != null) {
                    ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
                }
            }
            if (bean instanceof BeanFactoryAware) {
                ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
            }
        }
    }

如果我们的bean实例实现了上面的接口,会按照下面的顺序依次进行调用:

  1. BeanNameAware:将bean的名称注入进去
  2. BeanClassLoaderAware:将BeanClassLoader注入进去
  3. BeanFactoryAware:将BeanFactory注入进去

Bean初始化前操作

@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
    throws BeansException {

    Object result = existingBean;
    for (BeanPostProcessor processor : getBeanPostProcessors()) {
        Object current = processor.postProcessBeforeInitialization(result, beanName);
        if (current == null) {
            return result;
        }
        result = current;
    }
    return result;
}

会调用BeanPostProcessor的postProcessBeforeInitialization方法,若返回值为null,当前方法将结束。

通常称postProcessBeforeInitialization这个方法为:bean初始化前操作。

这个接口有2个实现类,比较重要: org.springframework.context.support.ApplicationContextAwareProcessor org.springframework.context.annotation.CommonAnnotationBeanPostProcessor

ApplicationContextAwareProcessor注入6个Aware接口对象

如果bean实现了下面的接口,在ApplicationContextAwareProcessor#postProcessBeforeInitialization中会依次调用下面接口中的方法,将Aware前缀对应的对象注入到bean实例中。

  • EnvironmentAware:注入Environment对象
  • EmbeddedValueResolverAware:注入EmbeddedValueResolver对象
  • ResourceLoaderAware:注入ResourceLoader对象
  • ApplicationEventPublisherAware:注入ApplicationEventPublisher对象
  • MessageSourceAware:注入MessageSource对象
  • ApplicationContextAware:注入ApplicationContext对象 从名称上可以看出这个类以ApplicationContext开头的,说明这个类只能在ApplicationContext环境中使用。

CommonAnnotationBeanPostProcessor调用@PostConstruct标注的方法

CommonAnnotationBeanPostProcessor#postProcessBeforeInitialization中会调用bean中所有标注@PostConstruct注解的方法。

Bean初始化操作

该阶段有两个步骤:

  1. 调用InitializingBean接口的afterPropertiesSet方法
  1. 调用定义bean的时候指定的初始化方法。

调用InitializingBean接口的afterPropertiesSet方法

public interface InitializingBean {

    void afterPropertiesSet() throws Exception;

}

当Bean实现了这个接口,会在该阶段被调用。

调用bean定义的时候指定的初始化方法

指定Bean的初始化方式有三种:

  1. xml方式指定初始化方法 <bean init-method="bean中方法名称"/>

  2. @Bean的方式指定初始化方法 @Bean(initMethod = "初始化的方法")

  3. Api的方式指定初始化方法 this.beanDefinition.setInitMethodName(methodName);

初始化方法最终会赋值给下面这个字段 org.springframework.beans.factory.support.AbstractBeanDefinition#initMethodName

Bean初始化后操作

@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
    throws BeansException {

    Object result = existingBean;
    for (BeanPostProcessor processor : getBeanPostProcessors()) {
        Object current = processor.postProcessAfterInitialization(result, beanName);
        if (current == null) {
            return result;
        }
        result = current;
    }
    return result;
}

调用BeanPostProcessor的postProcessAfterInitialization方法,若返回值为null则方法结束。 通常称postProcessAfterInitialization这个方法为:bean初始化后置操作。

Bean初始化完成操作

上述步骤完成后Bean的初始化完成,进入下个阶段

阶段十:所有单例Bena初始化完成后阶段

所有单例bean实例化完成之后,spring会回调下面这个接口:

public interface SmartInitializingSingleton {
    void afterSingletonsInstantiated();
}

调用逻辑在下面这个方法中:

/**
 * 确保所有非lazy的单例都被实例化,同时考虑到FactoryBeans。如果需要,通常在工厂设置结束时调用。
 */
org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons

该方法会触发所有非lazy-init的单例Bean的初始化,然后在容器中找到所有类型是SmartInitializingSingleton的Bean,调用它们的afterSingletoninstantiated方法。

阶段十一:Bean的使用阶段

调用getBean方法得到Bean进行使用。

阶段十二:Bean的销毁阶段

触发bean销毁的几种方式

  1. 调用org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#destroyBean
  1. 调用org.springframework.beans.factory.config.ConfigurableBeanFactory#destroySingletons
  1. 调用ApplicationContext中的close方法

Bean销毁阶段会依次执行

  1. 轮询beanPostProcessors列表,如果是DestructionAwareBeanPostProcessor这种类型的,会调用其内部的postProcessBeforeDestruction方法。DestructionAwareBeanPostProcessor接口有实现类CommonAnnotationBeanPostProcessor,该类中的postProcessBeforeDestruction方法会调用Bean中所有标注了@PreDestroy注解的方法。
  1. 如果bean实现了org.springframework.beans.factory.DisposableBean接口,会调用这个接口中的destroy方法
  1. 调用bean自定义的销毁方法,有三种方式:

方式1:xml中指定销毁方法

<bean destroy-method="bean中方法名称"/>

方式2:@Bean中指定销毁方法

@Bean(destroyMethod = "初始化的方法")

方式3:api的方式指定销毁方法

this.beanDefinition.setDestroyMethodName(methodName);

初始化方法最终会赋值给下面这个字段
org.springframework.beans.factory.support.AbstractBeanDefinition#destroyMethodName

销毁方法的调用顺序:

  1. @PreDestroy标注的所有方法
  1. DisposableBean接口中的destroy()
  1. 自定义的销毁方法