Spring容器系列-bean的生命周期

Spring容器系列-bean的生命周期

   概要

    对于Spring Bean的生命周期来说,可以分为四个阶段,其中初始化完成之后,就代表这个Bean可以使用了,四个阶段如下:

  •    实例化 Instantiation : 为Bean分配内存空间 
  •    属性赋值 Populate :将当前类依赖的Bean属性,进行注入和装配
  •    初始化 Initialization
  •    销毁 Destruction

    一、Spring Bean生命周期

    1.  Spring Bean 生命周期流程图

    先来看看Spring Bean生命周期流程图如下:

    

   下面对Spring Bean生命周期进行详细描述:

    1. Bean容器在配置文件中找到Spring Bean的定义。

    2. Bean容器使用Java Reflection API创建Bean的实例。

    3. 如果声明了任何属性,声明的属性会被设置。如果属性本身是Bean,则将对其进行解析和设置。

    4. 如果Bean类实现BeanNameAware接口,则将通过传递Bean的名称来调用setBeanName()方法。

    5. 如果Bean类实现BeanClassLoaderAware接口,则将通过传递加载此Bean的ClassLoader对象的实例来调用setBeanClassLoader()方法。

    6. 如果Bean类实现BeanFactoryAware接口,则将通过传递BeanFactory对象的实例来调用setBeanFactory()方法。

    7. 如果有任何与BeanFactory关联的BeanPostProcessors对象已加载Bean,则将在设置Bean属性之前调用postProcessBeforeInitialization()方法。

    8. 如果Bean类实现了InitializingBean接口,则在设置了配置文件中定义的所有Bean属性后,将调用afterPropertiesSet()方法。

    9. 如果配置文件中的Bean定义包含init-method属性,则该属性的值将解析为Bean类中的方法名称,并将调用该方法。

   10. 如果为Bean Factory对象附加了任何Bean 后置处理器,则将调用postProcessAfterInitialization()方法。

   11. 如果Bean类实现DisposableBean接口,则当Application不再需要Bean引用时,将调用destroy()方法。

   12. 如果配置文件中的Bean定义包含destroy-method属性,那么将调用Bean类中的相应方法定义。

   说明:4、5、6步骤都可以统一看做是第三阶段初始化中的检查aware相关接口并设置相关依赖

   2.  举个例子

   1)定义一个PersonBean类,实现了DisposableBean, InitializingBean, BeanFactoryAware, BeanNameAware这4个接口,同时还有自定义的init-methoddestroy-method。这里,如果不了解这几个接口的读者,可以先去看看这几个接口的定义。

复制代码
 1 public class PersonBean implements InitializingBean, BeanNameAware,BeanFactoryAware, DisposableBean {
 2     /**
 3      * 身份证号
 4      */
 5     private Integer idNo;
 6 
 7     /**
 8      * 姓名
 9      */
10     private String name;
11 
12     public PersonBean() {
13         System.out.println("1.调用构造方法:我出生了!");
14     }
15 
16     public Integer getIdNo() {
17         return idNo;
18     }
19 
20     public void setIdNo(Integer idNo) {
21         this.idNo = idNo;
22     }
23 
24     public String getName() {
25         return name;
26     }
27 
28     public void setName(String name) {
29         this.name = name;
30         System.out.println("2.设置属性:我的名字叫"+name);
31     }
32 
33     public void setBeanName(String name) {
34         System.out.println("3.调用BeanNameAware#setBeanName方法:我要上学了,起了个学名");
35 
36     }
37 
38     public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
39         System.out.println("4.调用BeanFactoryAware#setBeanFactory方法:选好学校了");
40     }
41 
42     public void afterPropertiesSet() throws Exception {
43         System.out.println("6.InitializingBean#afterPropertiesSet方法:入学登记");
44     }
45 
46     public void init() {
47         System.out.println("7.自定义init方法:努力上学ing");
48     }
49 
50     public void destroy() throws Exception {
51         System.out.println("9.DisposableBean#destroy方法:平淡的一生落幕了");
52     }
53 
54     public void destroyMethod() {
55         System.out.println("10.自定义destroy方法:睡了,别想叫醒我");
56     }
57 
58     public void work(){
59         System.out.println("Bean使用中:工作,只有对社会没有用的人才放假。。");
60     }
61 
62 }
复制代码

    2)定义一个MyBeanPostProcessor实现BeanPostProcessor接口。

复制代码
 1 public class MyBeanPostProcessor implements BeanPostProcessor {
 2     public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
 3         System.out.println("5.BeanPostProcessor.postProcessBeforeInitialization方法:到学校报名啦");
 4         return bean;
 5     }
 6 
 7     public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
 8         System.out.println("8.BeanPostProcessor#postProcessAfterInitialization方法:终于毕业,拿到毕业证啦!");
 9         return bean;
10     }
11 }
复制代码

    3)配置文件spring-config.xml,指定init-methoddestroy-method属性

复制代码
 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <beans xmlns="http://www.springframework.org/schema/beans"
 3        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 4        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
 5 
 6     <bean name="myBeanPostProcessor" class="ric.study.demo.ioc.life_cycle_demo_set.MyBeanPostProcessor" />
 7     <bean name="personBean" class="ric.study.demo.ioc.life_cycle_demo_set.Person"
 8           init-method="init" destroy-method="destroyMethod">
 9         <property name="name" value="Richard Yi" />
10     </bean>
11 
12 </beans>
复制代码

   4)启动类,运行代码

复制代码
 1     public static void main( String[] args )
 2     {
 3         ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
 4         PersonBean personBean = (PersonBean) context.getBean("personBean");
 5         personBean.work();
 6         ((ClassPathXmlApplicationContext) context).destroy();
 7 
 8     }
 9 
10 
11  //运行结果如下:
12  1.调用构造方法:我出生了!
13  2.设置属性:我的名字叫张铁钢
14  3.调用BeanNameAware#setBeanName方法:我要上学了,起了个学名
15  4.调用BeanFactoryAware#setBeanFactory方法:选好学校了
16  5.BeanPostProcessor.postProcessBeforeInitialization方法:到学校报名啦
17  6.InitializingBean#afterPropertiesSet方法:入学登记
18  7.自定义init方法:努力上学ing
19  8.BeanPostProcessor#postProcessAfterInitialization方法:终于毕业,拿到毕业证啦!
20  Bean使用中:工作,只有对社会没有用的人才放假。。
21  9.DisposableBean#destroy方法:平淡的一生落幕了
22  10.自定义destroy方法:睡了,别想叫醒我
23     
复制代码

    二、 Spring Bean生命周期源码分析

    Bean实例化的时机也分为两种,BeanFactory管理的Bean是在使用到Bean的时候才会实例化Bean,ApplicantContext管理的Bean在容器初始化的时候就会完成Bean实例化。

    1. getBean()方法

  AbstractApplicationContext类里的refresh方法,这个方法是 ApplicationContext 容器初始化的关键点。在这个方法里,调用了finishBeanFactoryInitialization方法,这个方法里调用了getBean方法,getBean方法里调用了AbstractBeanFactorygetBean方法。
    如下图:

  

    2.  createBean方法

    Bean的创建的入口是 AbstractAutowireCapableBeanFactory#createBean:

复制代码
// 这个类的核心方法,创建一个bean实例,填充bean实例,执行后处理等
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
    // ...
    tr {
        // 给 BeanPostProcessors 提供一个机会,允许它们在实例化 Bean 之前,决定是否返回代理对象,
        // 如果返回了代理对象,则跳过后续的实例化过程,直接返回该代理对象。
        Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
        // 直接返回代理对象,而不会继续执行实例化流程。
        if (bean != null) {
            return bean;
        }
       //...

    //负责执行 Bean 的实例化、依赖注入等   
    Object beanInstance = doCreateBean(beanName, mbdToUse, args);
    // 日志输出,记录创建 Bean 实例的完成信息(如果日志级别为 Debug)
    if (logger.isDebugEnabled()) {
        logger.debug("Finished creating instance of bean '" + beanName + "'");
    }
    // 返回已经创建并填充好的 Bean 实例。
    return beanInstance;
}
复制代码

    3. resolveBeforeInstantiation方法

    AbstractAutowireCapableBeanFactory#resolveBeforeInstantiation:

复制代码
@Nullable
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
    Object bean = null;
    
    // 检查是否已处理过实例化前的逻辑
    if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
        // 如果是合成 Bean 且没有自定义实例化后处理器,跳过处理
        if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
            // 确定目标类型
            Class<?> targetType = determineTargetType(beanName, mbd);
            if (targetType != null) {
                // 应用实例化前的 Bean 后处理器(如 AOP 代理)
                bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
                
                // 如果有 Bean 返回,执行初始化后处理,跳过了其他几个方法
                if (bean != null) {
                    bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
                }
            }
        }
        // 标记已解析
        mbd.beforeInstantiationResolved = (bean != null);
    }
    return bean;  // 返回代理或实际对象,若没有代理则为 null
}
复制代码

   resolveBeforeInstantiation 主要是用于 在 Bean 实例化之前做一些预处理工作,尤其是与AOP代理相关的处理。它的存在使得 Spring 能够在实例化之前决定是否需要为 Bean 创建代理对象,从而保证 AOP 增强能够正确地应用到 Bean 上。同时,它还能够优化性能,避免不必要的实例化过程。

   applyBeanPostProcessorsBeforeInstantiation方法中调用了InstantiationAwareBeanPostProcessor实现类的postProcessBeforeInstantiation方法。

   4.  InstantiationAwareBeanPostProcessor 接口

   部分源码如下:

复制代码
public interface InstantiationAwareBeanPostProcessor extends BeanPostProcessor {

    Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException;

    boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException;

    PropertyValues postProcessPropertyValues(
            PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException;

}
复制代码

    从源码中我们可以获知:InstantiationAwareBeanPostProcessor接口除了具有父接口中的两个方法(postProcessBeforeInitialization和postProcessAfterInitialization)以外还自己额外定义了三个方法。所以该接口一共定义了5个方法。

   InstantiationAwareBeanPostProcessor 是 Spring 提供的一个后置处理器接口,专门用于在 Bean 实例化过程中的不同阶段对 Bean 进行额外的操作。它扩展了 BeanPostProcessor 接口,提供了比 BeanPostProcessor 更细粒度的处理能力,尤其是在 Bean 实例化和属性填充时。

    注意这两个单词:

  • Instantiation:表示实例化,对象还未生成
  • Initialization:表示初始化,对象已经生成

   5.  CommonAnnotationBeanPostProcessor

   CommonAnnotationBeanPostProcessor实现了InstantiationAwareBeanPostProcessor接口,它是AnnotationConfigApplicationContext初始化时注入的6个内部bean之一。

   主要处理*@Resource、@PostConstruct和@PreDestroy*注解的实现,@Resource的处理是由他自己完成,@PostConstruct和@PreDestroy这两个是由他的父类 InitDestroyAnnotationBeanPostProcessor完成

   在postProcessMergedBeanDefinition方法中,其父类InitDestroyAnnotationBeanPostProcessor会寻找@PostConstruct和@PreDestroy注解,他本身会寻找@Resource注解

复制代码
CommonAnnotationBeanPostProcessor
@Override
    public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
        // 父类处理@PostConstruct和@PreDestroy注解
        super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
        // 处理@Resource注解
        InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
        metadata.checkConfigMembers(beanDefinition);
    }
    
InitDestroyAnnotationBeanPostProcessor
@Override
    public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
        //找出被@PostConstruct和@PreDestroy注解修饰的方法
        LifecycleMetadata metadata = findLifecycleMetadata(beanType);
        // 去除重复,并注册到beanDefinition中
        metadata.checkConfigMembers(beanDefinition);
    }
复制代码

 

   @PostConstruct注解的方法会在InitDestroyAnnotationBeanPostProcessor类的postProcessBeforeInitialization中进行调用处理,@PreDestroy注解的方法会在InitDestroyAnnotationBeanPostProcessor类的postProcessBeforeDestruction中进行调用

 

复制代码
InitDestroyAnnotationBeanPostProcessor
@Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
        try {
            metadata.invokeInitMethods(bean, beanName);
        }
        ...
        return bean;
    }
@Override
    public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
        LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
        try {
            metadata.invokeDestroyMethods(bean, beanName);
        }
        ...
    }
复制代码

 

    6. doCreateBean方法

  AbstractAutowireCapableBeanFactory#doCreateBean方法:

复制代码
 1 protected Object doCreateBean(String beanName,RootBeanDefinition mbd,@Nullable Object [args) throws BeanCreationException {
 2 
 3     // 实例化bean.
 4     BeanWrapper instanceWrapper = null;
 5     if (mbd.isSingleton()) {
 6         instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
 7     }
 8     if (instanceWrapper == null) {
 9         instanceWrapper = createBeanInstance(beanName, mbd, args);
10     }
11 
12     ...
13 
14     Object exposedObject = bean;
15     try {
16 
17       //为bean设置属性值
18       populateBean(beanName,mbd,instanceWrapper);
19 
20       //初始化bean
21       exposedObject = initializeBean(beanName,exposedObject,mbd);
22     }
23     ...
24 
25     return exposedObject;
26 }
复制代码

   doCreateBean方法中相关的就是populateBean方法和initializeBean方法,populateBean方法主要为bean设置属性值,我们重点关注初始化Bean方法initializeBean。

   7.  populateBean方法

   AbstractAutowireCapableBeanFactory#populateBean: 

复制代码
protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
    //...

    // 让 InstantiationAwareBeanPostProcessor 有机会在属性填充前修改 Bean 的状态
    if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                // 调用 postProcessAfterInstantiation 检查是否可以继续进行属性注入
                if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {
                    return; // 如果返回 false,跳过属性注入
                }
            }
        }
    }
    //...
    // 如果有 InstantiationAwareBeanPostProcessors,执行属性处理
    if (hasInstAwareBpps) {
        if (pvs == null) {
            pvs = mbd.getPropertyValues();
        }
        for (BeanPostProcessor bp : getBeanPostProcessors()) {
            if (bp instanceof InstantiationAwareBeanPostProcessor) {
                InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
                // 使用 postProcessProperties 处理 Bean 属性
                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;
            }
        }
    }

    //...

    // 真正设置属性的方法: 如果属性值不为空,应用属性值到Bean中
    if (pvs != null) {
        applyPropertyValues(beanName, mbd, bw, pvs);
    }
}
复制代码

   通过 postProcessProperties 和 postProcessPropertyValues,允许 InstantiationAwareBeanPostProcessor 在属性注入前后修改 Bean 的属性值。这个操作是动态的,可能会根据实际情况调整属性值或跳过属性注入。

   8. initializeBean方法

   AbstractAutowireCapableBeanFactory#initializeBean

复制代码
 1 protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
 2     if (System.getSecurityManager() != null) {
 3         AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
 4             // 激活 Aware 方法
 5             invokeAwareMethods(beanName, bean);
 6             return null;
 7         }, getAccessControlContext());
 8     }
 9     else {
10         // 对特殊的 bean 处理:BeanNameAware、BeanClassLoaderAware、BeanFactoryAware,使得 Bean 可以访问一些容器中特定的资源
11         invokeAwareMethods(beanName, bean);
12     }
13 
14     Object wrappedBean = bean;
15     if (mbd == null || !mbd.isSynthetic()) {
16         //执行BeanPostProcessor所有实现类的postProcessBeforeInitialization方法
17         wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
18     }
19 
20     try {
21         // 激活用户自定义的 init 方法
22         invokeInitMethods(beanName, wrappedBean, mbd);
23     }
24     catch (Throwable ex) {
25         throw new BeanCreationException(
26                 (mbd != null ? mbd.getResourceDescription() : null),
27                 beanName, "Invocation of init method failed", ex);
28     }
29     if (mbd == null || !mbd.isSynthetic()) {
30        //执行BeanPostProcessor所有实现类的postProcessAfterInitialization方法
31         wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
32     }
33     return wrappedBean;
34 }
复制代码

     AbstractAutowireCapableBeanFactory#invokeAwareMethods

复制代码
 1 private void invokeAwareMethods(String beanName, Object bean) {
 2     // 1. 检查 Bean 是否实现了 Aware 接口
 3     if (bean instanceof Aware) {
 4         // 2. 如果 Bean 实现了 BeanNameAware 接口
 5         if (bean instanceof BeanNameAware) {
 6             // 调用 setBeanName 方法,设置 Bean 的名称
 7             ((BeanNameAware) bean).setBeanName(beanName);
 8         }
 9         // 3. 如果 Bean 实现了 BeanClassLoaderAware 接口
10         if (bean instanceof BeanClassLoaderAware) {
11             ClassLoader bcl = getBeanClassLoader(); // 获取 Bean 的类加载器
12             if (bcl != null) {
13                 // 调用 setBeanClassLoader 方法,设置类加载器
14                 ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
15             }
16         }
17         // 4. 如果 Bean 实现了 BeanFactoryAware 接口
18         if (bean instanceof BeanFactoryAware) {
19             // 调用 setBeanFactory 方法,设置 BeanFactory
20             ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
21         }
22     }
23 }
复制代码

    说明:Spring在创建Bean时进行的一部分初始化工作,确保每个Bean在被使用之前已经具备了必要的依赖和环境信息。

    AbstractAutowireCapableBeanFactory#invokeInitMethods

复制代码
 1 protected void invokeInitMethods(String beanName, Object bean, @Nullable RootBeanDefinition mbd)
 2             throws Throwable {
 3         // 判断当前bean是否实现了InitializingBean接口
 4         boolean isInitializingBean = (bean instanceof InitializingBean);
 5         // 如果当前bean是一个InitializingBean
 6         if (isInitializingBean && (mbd == null || !mbd.hasAnyExternallyManagedInitMethod("afterPropertiesSet"))) {
 7             if (logger.isTraceEnabled()) {
 8                 logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
 9             }
10             if (System.getSecurityManager() != null) {
11                 try {
12                     AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
13                         ((InitializingBean) bean).afterPropertiesSet();
14                         return null;
15                     }, getAccessControlContext());
16                 }
17                 catch (PrivilegedActionException pae) {
18                     throw pae.getException();
19                 }
20             }
21             else {
22                 // 真正调用当前bean的afterPropertiesSet方法
23                 ((InitializingBean) bean).afterPropertiesSet();
24             }
25         }
26 
27        if (mbd != null && bean.getClass() != NullBean.class) {
28             String initMethodName = mbd.getInitMethodName();
29             if (StringUtils.hasLength(initMethodName) &&
30                     !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
31                     !mbd.hasAnyExternallyManagedInitMethod(initMethodName)) {
32                 // 最后通过反射的方式执行init-method属性对应的方法
33                 invokeCustomInitMethod(beanName, bean, mbd);
34             }
35         }
36 }
复制代码

    9. afterPropertiesSet()方法

    InitializingBean只有一个方法afterPropertiesSet,见名知意,这个方法是在bean的属性值被设置以后执行。 Spring给我们提供了这么一个扩展点,可以用来做很多的事情, 比如可以修改默认设置的属性,添加补充额外的属性值或者针对关键属性做一个校验。

    Spring本身也有很多的Bean实现了InitializingBean接口, 比如Spring MVC中的RequestMappingHandlerMapping就实现了InitializingBean接口,在afterPropertiesSet中完成了一些初始化工作,比如url和controller方法的映射。

    说明:InitializingBean是Spring中很关键的一个扩展接口,其实它和bean中init-method属性对应的方法功能是一致的,都是初始化bean,我们可以二选一实现即可,当然同时使用也没有问题。init-method是通过反射实现的,性能相对差一点点。另外,如果调用afterPropertiesSet方法时出错,则不会调用init-method指定的方法。

    四、Bean生命周期中AOP的流程

    1.  @EnableAspectJAutoProxy

    通过@EnableAspectJAutoProxy注解向容器中注册一个AnnotationAwareAspectJAutoProxyCreator的BeanDefinition,它本身也是一个BeanPostProcessor,这个BeanDefinition会在org.springframework.context.support.AbstractApplicationContext#registerBeanPostProcessors这个方法中完成创建。

    AnnotationAwareAspectJAutoProxyCreator中比较重要的几个方法都是继承自父类AbstractAutoProxyCreator

    部分源码如下:

复制代码
public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator {

    /**
     * 此方法是在 Bean 实例化之前执行
    */
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
        // 获取缓存的key
        Object cacheKey = getCacheKey(beanClass, beanName);

        // 如果beanName为空或者当前bean不需要代理,直接跳过
        if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
            if (this.advisedBeans.containsKey(cacheKey)) {
                return null; // 如果已经被代理过,返回null
            }
            // 如果是基础设施类,或者满足跳过条件,则不需要代理
            if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
                this.advisedBeans.put(cacheKey, Boolean.FALSE);
                return null; // 不需要代理,返回null
            }
        }

        // 如果有自定义的 TargetSource,则通过 TargetSource 创建代理
        TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
        if (targetSource != null) {
            // 如果 beanName 不为空,将其添加到 targetSourcedBeans 中
            if (StringUtils.hasLength(beanName)) {
                this.targetSourcedBeans.add(beanName);
            }
            // 获取与当前bean相关的拦截器和增强
            Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
            // 创建代理对象
            Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
            // 将代理类型缓存
            this.proxyTypes.put(cacheKey, proxy.getClass());
            return proxy; // 返回创建的代理对象
        }

        return null; // 如果没有代理,返回null
    }

    /**
     * 此方法是在 Bean 实例化完成之后执行
     */
    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) {
        // 默认返回true,表示允许对该bean继续进行属性设置等操作
        return true;
    }
    /**
     * 此方法是是Spring AOP 中的一个钩子方法,它在 Bean 初始化之前执行,通常用于做一些初步的修改或检查。在默认实现中,没有做任何修改,直接返回原始 Bean
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        return bean;
    }

    /**
     * 此方法是在 Bean 初始化完成之后执行,通常用于创建代理(例如 AOP 代理)
     * 如果需要代理 Bean,会调用 wrapIfNecessary 方法来进行实际的代理创建。如果 Bean 不需要代理,直接返回原始 Bean。
     */
    @Override
    public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
        if (bean != null) {
            // 计算缓存的 key
            Object cacheKey = getCacheKey(bean.getClass(), beanName);

            // 如果早期代理引用被移除,则开始进行包装处理
            if (this.earlyProxyReferences.remove(cacheKey) != bean) {
                return wrapIfNecessary(bean, beanName, cacheKey); // 进行代理包装
            }
        }
        // 返回原始bean,或者是代理对象
        return bean; 
    }

    //...
}
复制代码

   2.  postProcessBeforeInstantiation方法执行

   执行AnnotationAwareAspectJAutoProxyCreator的postProcessBeforeInstantiation方法,实际上就是父类AbstractAutoProxyCreator的postProcessBeforeInstantiation被执行

   3. postProcessAfterInitialization方法执行

   执行AnnotationAwareAspectJAutoProxyCreator的postProcessAfterInitialization方法,实际上也是执行父类AbstractAutoProxyCreator中的方法。

   AOP代理的创建就是在这里完成的。

   createBean中调用的resolveBeforeInstantiation,调用postProcessBeforeInstantiation为 Bean 创建代理对象返回不为null,则执行初始化后处理,跳过了其他几个方法

 

   五、容器关闭

    1. bean的销毁入口

    如下图:

    

    2. Bean的销毁过程触发时机

    1)在Spring 中执行显式关闭上下文,关闭时候会执行实现DisposableBean接口类中的destroy() 方法    

1 ConfigurableApplicationContext context = new ClassPathXmlApplicationContext(new String[] {"spring.xml"});
2 // 以下两种显式关闭都会调用实现了DisposableBean接口类中的destroy() 方法
3 // 1、显式关闭上下文
4 context.close();
5 // 2、显式关闭上下文
6 context.registerShutdownHook();

    2)web环境中,Tomcat关闭

    在Web环境中,当Tomcat关闭的时候就会调用到 servlet中的销毁方法,在这个方法中就会最终也会掉用到Spring中 DisposableBeanAdapter类的destroy()方法,该方法就会根据前面的收集进行调用。

复制代码
 1 public class ContextLoaderListener extends ContextLoader implements ServletContextListener {
 2     public ContextLoaderListener() {
 3     }
 4 
 5     public ContextLoaderListener(WebApplicationContext context) {
 6         super(context);
 7     }
 8 
 9     public void contextInitialized(ServletContextEvent event) {
10         this.initWebApplicationContext(event.getServletContext());
11     }
12     //  servlet中的销毁方法
13     public void contextDestroyed(ServletContextEvent event) {
14        // 该方法最终会调用Spring的DisposableBeanAdapter类的destroy()
15         this.closeWebApplicationContext(event.getServletContext());
16         ContextCleanupListener.cleanupAttributes(event.getServletContext());
17     }
复制代码

    servlet中的closeWebApplicationContext方法最终也会掉用到Spring中的DisposableBeanAdapter类的destroy()方法,该方法就会根据前面的收集进行调用。 

    3. 销毁过程解析

   与Bean初始化类似,当容器关闭时,可以看到对Bean销毁方法的调用。销毁过程是这样的。顺着close()-> doClose() -> destroyBeans() -> destroySingletons() -> destroySingleton() -> destroyBean() -> bean.destroy() ,会看到最终调用Bean的销毁方法。

    AbstractApplicationContext#close(),其实实现的是ConfigurableApplicationContext的close()方法

复制代码
 1     @Override
 2     public void close() {
 3         synchronized (this.startupShutdownMonitor) {
 4             doClose();
 5             // If we registered a JVM shutdown hook, we don't need it anymore now:
 6             // We've already explicitly closed the context.
 7             if (this.shutdownHook != null) {
 8                 try {
 9                     Runtime.getRuntime().removeShutdownHook(this.shutdownHook);
10                 }
11                 catch (IllegalStateException ex) {
12                     // ignore - VM is already shutting down
13                 }
14             }
15         }
16     }
复制代码

    DefaultSingletonBeanRegistry#destroyBean()源码如下:  

复制代码
 1 protected void destroyBean(String beanName, DisposableBean bean) {
 2         // 忽略
 3 
 4         // Actually destroy the bean now...
 5         if (bean != null) {
 6             try {
 7                 bean.destroy();
 8             }
 9             catch (Throwable ex) {
10                 logger.error("Destroy method on bean with name '" + beanName + "' threw an exception", ex);
11             }
12         }
13 
14         // 忽略
15
复制代码

   这里注意哦,这个Bean的类型实际上是DisposableBeanAdapter。

   3. DisposableBeanAdapter

  DisposableBeanAdapter是用来管理Spring Bean的销毁的,实际上这里运用了适配器模式。负责将各种销毁方式适配为统一的 destroy() 方法,以便 Spring 容器在关闭时一致地调用。

   AbstractAutowireCapableBeanFactory#doCreateBean

复制代码
 1 try {
 2     ... 
 3     
 4     //注册bean销毁时的类DisposableBeanAdapter:如果实现了 DisposableBean接口或者提供了destroy—method 在这里注册
 5     registerDisposableBeanIfNecessary(beanName, bean, mbd);
 6 }
 7 catch (BeanDefinitionValidationException ex) {
 8     throw new BeanCreationException(
 9         mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
10 }
复制代码

   源码位置:AbstractBeanFactory#registerDisposableBeanIfNecessary()

复制代码
 1 protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
 2         AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
 3         if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
 4             if (mbd.isSingleton()) {
 5                 // 注册一个DisposableBean实现,该实现将执行给定bean的所有销毁工作。
 6                 // 包括:DestructionAwareBeanPostProcessors,DisposableBean接口,自定义destroy方法。
 7                 registerDisposableBean(beanName,
 8                         new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
 9             }
10             else {
11                 // A bean with a custom scope...
12                 Scope scope = this.scopes.get(mbd.getScope());
13                 if (scope == null) {
14                     throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
15                 }
16                 scope.registerDestructionCallback(beanName,
17                         new DisposableBeanAdapter(bean, beanName, mbd, getBeanPostProcessors(), acc));
18             }
19         }
20     }
复制代码

  再来看看destroy()的具体方法。

  DisposableBeanAdapter#destroy()源码如下:

复制代码
 1 @Override
 2     public void destroy() {
 3         if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
 4             for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
 5                 processor.postProcessBeforeDestruction(this.bean, this.beanName);
 6             }
 7         }
 8 
 9         if (this.invokeDisposableBean) {
10             if (logger.isDebugEnabled()) {
11                 logger.debug("Invoking destroy() on bean with name '" + this.beanName + "'");
12             }
13             try {
14                 if (System.getSecurityManager() != null) {
15                     AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
16                         @Override
17                         public Object run() throws Exception {
18                             ((DisposableBean) bean).destroy();
19                             return null;
20                         }
21                     }, acc);
22                 }
23                 else {
24                     // 调用 DisposableBean 的 destroy()方法
25                     ((DisposableBean) bean).destroy();
26                 }
27             }
28             catch (Throwable ex) {
29                 String msg = "Invocation of destroy method failed on bean with name '" + this.beanName + "'";
30                 if (logger.isDebugEnabled()) {
31                     logger.warn(msg, ex);
32                 }
33                 else {
34                     logger.warn(msg + ": " + ex);
35                 }
36             }
37         }
38 
39         if (this.destroyMethod != null) {
40             // 调用 设置的destroyMethod
41             invokeCustomDestroyMethod(this.destroyMethod);
42         }
43         else if (this.destroyMethodName != null) {
44             Method methodToCall = determineDestroyMethod();
45             if (methodToCall != null) {
46                 invokeCustomDestroyMethod(methodToCall);
47             }
48         }
49     }
复制代码

   

   参考链接:

   https://segmentfault.com/a/1190000020747302

   https://juejin.cn/post/7075168883744718856

   https://yangzhiwen911.github.io/

 

posted @   欢乐豆123  阅读(911)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示