Spring Bean 的生命周期

193 阅读10分钟

大纲

Springbean的生命周期总览

  1. Bean元信息配置阶段
  2. Bean元信息解析阶段
  3. 将Bean注册到容器中
  4. BeanDefinition合并阶段
  5. Bean Class加载阶段
  6. Bean实例化阶段(3个小阶段)
    • Bean实例化前阶段
    • Bean实例化阶段
  7. 属性赋值阶段(3个小阶段)
    • Bean实例化后阶段
    • Bean属性赋值前处理
    • Bean属性赋值
  8. Spring Bean Aware接口回调阶段
  9. Bean属性赋值前阶段
  10. Spring Bean 初始化阶段
    • Bean Aware接口回调
    • Bean 初始化前操作
    • Bean 初始化操作
    • Bean 初始化后操作
    • Bean 初始化完成操作
  11. Spring Bean的使用阶段
  12. Spring Bean 销毁阶段
    • Spring Bean 销毁前阶段
    • Spring Bean 销毁阶段
  13. Spring Bean 垃圾收集

1. Bean元信息配置阶段

参考 注解的方式配置元信息

这一阶段Java程序员通过 XML、Properties、Java注解等形式定义Bean的元信息。

2. Bean元信息解析阶段

元信息解析阶段做的事情是把定义好的Bean元信息解析为BeanDefinition对象。

package bean.beandifinition;

import ioc.User;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Map;

/**
 * 注解能力 {@link ApplicationContext} 作为 IoC 容器示例
 *
 * @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
 * @since
 */
@Configuration
public class AnnotationBeanDefinitionParseDemo {

    public static void main(String[] args) {
        // 创建 BeanFactory 容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        // 将当前类 AnnotationApplicationContextAsIoCContainerDemo 作为配置类(Configuration Class)
        applicationContext.register(AnnotationBeanDefinitionParseDemo.class);
        // 启动应用上下文
        applicationContext.refresh();
        // 从注解元信息定义形式 解析BeanDefinition
        for (String beanName : applicationContext.getBeanDefinitionNames()) {
            if(!"xiaomage".equals(beanName))  continue;
            BeanDefinition beanDefinition = applicationContext.getBeanDefinition(beanName);
            //获取BeanDefinition具体使用的是哪个类
            String beanDefinitionClassName = beanDefinition.getClass().getName();
            //通过名称获取bean对象
            Object bean = applicationContext.getBean(beanName);
            //打印输出
            System.out.println(beanName + ":");
            System.out.println("    beanDefinitionClassName:" + beanDefinitionClassName);
            System.out.println("    beanDefinition:" + beanDefinition);
            System.out.println("    bean:" + bean);
        }

        // 关闭应用上下文
        applicationContext.close();
    }
    /**
     * 通过 Java 注解的方式,定义了一个 Bean
     */
    @Bean(name="xiaomage")
    public User user() {
        User user = new User();
        user.setId(1L);
        user.setName("小马哥");
        return user;
    }

}

// 输出
xiaomage:
    beanDefinitionClassName:org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader$ConfigurationClassBeanDefinition
    beanDefinition:Root bean: class [null]; scope=; abstract=false; lazyInit=null; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=annotationBeanDefinitionParseDemo; factoryMethodName=user; initMethodName=null; destroyMethodName=(inferred); defined in bean.beandifinition.AnnotationBeanDefinitionParseDemo
    bean:User{id=1, name='小马哥'}

3. bean的注册阶段: 将Bean注册到容器中

bean注册阶段需要用到一个非常重要的接口:BeanDefinitionRegistry

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有个实现类:DefaultListableBeanFactory 示例代码

//创建一个bean工厂,这个默认实现了BeanDefinitionRegistry接口,所以也是一个bean注册器
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
//定义一个bean
GenericBeanDefinition nameBdf = new GenericBeanDefinition();
nameBdf.setBeanClass(String.class);
nameBdf.getConstructorArgumentValues().addIndexedArgumentValue(0, "Hello Spring!");
// 注册bean到容器中
factory.registerBeanDefinition("aString", nameBdf);

factory.registerAlias("aString", "bString");
System.out.println(factory.getBean("aString"));
System.out.println(factory.getBean("bString"));

4. BeanDefinition合并阶段

我们定义bean的时候有父子bean关系,此时子BeanDefinition中的信息是不完整的

org.springframework.beans.factory.support.AbstractBeanFactory#getMergedBeanDefinition bean定义可能存在多级父子关系,合并的时候进进行递归合并,最终得到一个包含完整信息的RootBeanDefinition

5. Bean Class加载阶段

BeanDefinition中有个Object类型的字段:beanClass private volatile Object beanClass; 用来表示bean的class对象,通常这个字段的值有2种类型,一种是bean对应的Class类型的对象,另一种是bean对应的Class的完整类名,第一种情况不需要解析,第二种情况:即这个字段是bean的类名的时候,就需要通过类加载器将其转换为一个Class对象。

6. Bean实例化阶段

6.1 Bean实例化前阶段

// DefaultListableBeanFactory这个类中有个非常非常重要的字段:
private final List<BeanPostProcessor> beanPostProcessors = new CopyOnWriteArrayList<>();

Bean实例化之前会调用一段代码

// AbstractAutowireCapableBeanFactory.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;
}

// postProcessBeforeInstantiation方法默认是空,用户可以覆盖实现来做到直接实例化一个bean实例
default Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
    return null;
}

上面代码中轮询beanPostProcessors列表,如果类型是InstantiationAwareBeanPostProcessor,尝试调用InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation获取bean的实例对象,如果能够获取到,那么将返回值作为当前bean的实例,那么spring这里开了一个口子,允许开发者通过这个方法直接创建对象跳过Spring后面的实例化阶段。

public class Test1 {
    public static class Car {
        private String name;
        public Car() {
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }

        @Override
        public String toString() {
            return "Car{" +
                    "name='" + name + ''' +
                    '}';
        }
    }

    @Test
    public  void test1() {
        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
        //添加一个BeanPostProcessor:InstantiationAwareBeanPostProcessor
        factory.addBeanPostProcessor(new InstantiationAwareBeanPostProcessor() { //@1
            @Nullable
            @Override
            public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
                System.out.println("调用postProcessBeforeInstantiation()");
                //发现类型是Car类型的时候,硬编码创建一个Car对象返回
                if (beanClass == Car.class) {
                    Car car = new Car();
                    car.setName("保时捷");
                    return car;
                }
                return null;
            }
        });

        //定义一个car bean,车名为:奥迪
        AbstractBeanDefinition carBeanDefinition = BeanDefinitionBuilder.
                genericBeanDefinition(Car.class).
                addPropertyValue("name", "奥迪").  //@2
                getBeanDefinition();
        factory.registerBeanDefinition("car", carBeanDefinition);
        //从容器中获取car这个bean的实例,输出
        System.out.println(factory.getBean("car"));
    }
}

// 输出 
调用postProcessBeforeInstantiation()
Car{name='保时捷'}

6.2 Bean实例化阶段

// AbstractAutowireCapableBeanFactory.determineConstructorsFromBeanPostProcessors
protected Constructor<?>[] determineConstructorsFromBeanPostProcessors(@Nullable Class<?> beanClass, String beanName)
      throws BeansException {

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

这个过程会决定构造器determineCandidateConstructors用于bean的实例化

7 合并后的BeanDefinition处理

// 合并后的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);
            }
        }
    }

会调用MergedBeanDefinitionPostProcessor接口的postProcessMergedBeanDefinition方法 void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName);
postProcessMergedBeanDefinition有2个实现类

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

8 Bean的属性赋值阶段

8.1 实例化后阶段

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

for (BeanPostProcessor bp : getBeanPostProcessors()) {
    if (bp instanceof InstantiationAwareBeanPostProcessor) {
        InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
        if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
            return;
        }
    }
}

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

8.2 属性赋值前阶段

会调用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;
    }
}

从上面可以看出,如果InstantiationAwareBeanPostProcessor中的postProcessPropertiespostProcessPropertyValues都返回空的时候,表示这个bean不需要设置属性,直接返回了,直接进入下一个阶段。

@Nullable
default PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName)
    throws BeansException {
    return null;
}

PropertyValues中保存了bean实例对象中所有属性值的设置,所以我们可以在这个这个方法中对PropertyValues值进行修改。 修改的方式

// 匿名内部类的方式
factory.addBeanPostProcessor(new InstantiationAwareBeanPostProcessor()

这个方法有2个比较重要的实现类 AutowiredAnnotationBeanPostProcessor在这个方法中对@Autowired、@Value标注的字段、方法注入值。 CommonAnnotationBeanPostProcessor在这个方法中对@Resource标注的字段和方法注入值。

8.3 属性赋值阶段

if (pvs != null) {
   applyPropertyValues(beanName, mbd, bw, pvs);
}

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

9 Bean初始化阶段

9.1 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);
            }
        }
    }

依次做了下面三个事情

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

9.2 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初始化前操作。 这个方法所在接口有两个重要的实现类

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对象

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

9.3 Bean初始化操作

2个步骤

  1. 调用InitializingBean接口的afterPropertiesSet方法
  2. 调用定义bean的时候指定的初始化方法。
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

9.4 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初始化后置操作。

9.5 Bean初始化完成操作

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

public interface SmartInitializingSingleton {
    void afterSingletonsInstantiated();
}

调用逻辑在下面的方法

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

这个方法内部会先触发所有非延迟加载的单例bean初始化,然后从容器中找到类型是SmartInitializingSingleton的bean,调用他们的afterSingletonsInstantiated方法。

10 Bean的销毁阶段

触发bean销毁的几种方式

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

Bean销毁阶段会依次执行

  1. 轮询beanPostProcessors列表,如果是DestructionAwareBeanPostProcessor这种类型的,会调用其内部的postProcessBeforeDestruction方法。
  2. 如果bean实现了org.springframework.beans.factory.DisposableBean接口,会调用这个接口中的destroy方法。
  3. 调用bean自定义的销毁方法

自定义销毁方法有3种方式

  • 方式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标注的所有方法
  2. DisposableBean接口中的destroy()
  3. 自定义的销毁方法

11 全局视野

image.png

BeanFactory接口,Bean工厂的顶层接口, IoC的底层容器。

DefaultListableBeanFactory类 实现了BeanFactory接口,可以说这个可以是BeanFactory接口真正的唯一实现,内部真正实现了bean生命周期中的所有代码。 其他的一些类都是依赖于DefaultListableBeanFactory类,将请求转发给DefaultListableBeanFactory进行bean的处理的。

AbstractApplicationContext类有两个比较重要的方法。

public abstract ConfigurableListableBeanFactory getBeanFactory() throws IllegalStateException;
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory)

我们使用AnnotationConfigApplicationContext的时候,经常调用reflush方法,这个方法内部就会调用上面这2个方法。

  • 第一个方法:getBeanFactory() 返回当前应用上下文中的ConfigurableListableBeanFactory,这也是个接口类型的,这个接口有一个唯一的实现类:DefaultListableBeanFactory。 有没有很熟悉,上面说过:DefaultListableBeanFactory是BeanFactory真正的唯一实现。 应用上线文中就会使用这个ConfigurableListableBeanFactory来操作Spring容器。

  • 第二个方法:registerBeanPostProcessors 说的通俗点:这个方法就是向ConfigurableListableBeanFactory中注册BeanPostProcessor,内容会从spring容器中获取所有类型的BeanPostProcessor,将其添加到DefaultListableBeanFactory#beanPostProcessors列表中

protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}

会调用 PostProcessorRegistrationDelegate#registerBeanPostProcessors 内部主要用到了4个BeanPostProcessor类型的List集合

List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<BeanPostProcessor> orderedPostProcessors
List<BeanPostProcessor> nonOrderedPostProcessors;
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();

当到这个方法的时候,spring容器中已经完成了所有Bean的注册

image.png