Spring源码之Bean的生命周期

        Spring已经成为了目前最流行的第三方开源框架之一,我们在充分享受Spring IOC容器带来的便捷时,也应该考虑一下Spring这个大工厂是如何将一个个的Bean生产出来的,我们一起来讨论一下Spring中Bean的生命周期。

        Spring容器就好像生产车间的流水线,创建出来的对象就像是生产出来的一个个精美绝伦的产品。 Spring将管理的对象称之为Bean。

        Spring最重要的功能就是帮助程序员创建对象(也就是IOC),而启动Spring就是为创建Bean对象做准备,所以我们先明白Spring到底是怎么去创建Bean的,也就是先弄明白Bean的生命周期。Bean的生命周期就是指:在Spring中,一个Bean是如何生成的,如何销毁的。

      Bean的一生总体上来说可以分为三个阶段:

  • 容器启动阶段
  • Bean的生成
  • Bean的销毁

一、容器启动阶段

        容器的启动阶段做了很多的预热工作,为后面Bean的实例化做好了充分的准备。

        1. 容器的初始化

        以AnnotationConfigApplicationContext容器为例,我们看它的构造函数:

	public AnnotationConfigApplicationContext() {
		this.reader = new AnnotatedBeanDefinitionReader(this);
		this.scanner = new ClassPathBeanDefinitionScanner(this);
	}

        首先,它会初始化一个AnnotatedBeanDefinitionReader为BeanDefinition读取器,它可以直接把某个类转换为BeanDefinition,并且会解析该类上的注解,比如:

    @Test
    public void testAnnotatedBeanDefinitionReader() {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ScanBean.class);
        AnnotatedBeanDefinitionReader annotatedBeanDefinitionReader = new AnnotatedBeanDefinitionReader(applicationContext);
        // 将Teacher.class解析为BeanDefinition
        annotatedBeanDefinitionReader.register(Teacher.class);
        System.out.println(applicationContext.getBean("teacher"));
    }

        另外,ClassPathBeanDefinitionScanner是扫描器,但是它的作用和BeanDefinitionReader类似,它可以进行扫描,扫描某个包路径,对扫描到的类进行解析,比如,扫描到的类上如果存在@Component注解,那么就会把这个类解析为一个BeanDefinition,比如:

    @Test
    public void testClassPathBeanDefinitionScanner() {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        applicationContext.refresh();
        ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(applicationContext);
        scanner.scan("cn.kieasar");
        System.out.println(applicationContext.getBean("goodsService"));
    }

        2、BeanDefination

        在Java世界中,万物皆对象,散落于程序代码各处的注解以及保存在磁盘上的xml或者其他文件等等配置元信息,在内存中总要以一种对象的形式表示,就好比我们活生生的人对应到Java世界中就是一个Person类。

        而Spring在内存中表示这些对象的方式就是BeanDefination,Bean对象被加载到内存之后是以BeanDefination的形式存在。

      3、BeanDefinationRegistry

        这样我们需要创建某一个对象实例的时候,找到相应的BeanDefination然后创建对象即可。那么我们需要某一个对象的时候,去哪里找到对应的BeanDefination呢?

        通过Bean定义的id找到对象的BeanDefination的对应关系或者说映射关系又是如何保存的呢?这就引出了BeanDefinationRegistry了。

        Spring通过BeanDefinationReader将对象加载到内存生成相应的BeanDefination之后,就将其注册到BeanDefinationRegistry中,BeanDefinationRegistry就是一个存放BeanDefination的大篮子,它也是一种键值对的形式,通过特定的Bean定义的id,映射到相应的BeanDefination。

        4、BeanFactoryPostProcessor

        BeanFactoryPostProcessor是容器启动阶段Spring提供的一个扩展点,主要负责对注册到BeanDefinationRegistry中的一个个的BeanDefination进行一定程度上的修改与替换。

        比如通过以下代码定义一个BeanPostProcessor: 

@Component
public class KieasarBeanPostProcessor implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (beanName.equals("teacher")) {
            System.out.println("初始化前" + bean);
        }
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (beanName.equals("teacher")) {
            System.out.println("初始化后" + bean);
        }
        return bean;
    }
}

        一个BeanPostProcessor可以在任意一个Bean的初始化之前和初始化之后去做一些自定义的逻辑,当然,我们可以通过判断beanName来进行针对性处理(针对某个Bean,或某部分
Bean),通过定义BeanPostProcessor可以干涉Spring创建Bean的过程。

        例如配置Jdbc的DataSource连接的时候可以这样配置:

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">  
    <property name="maxIdle" value="${jdbc.maxIdle}"></property>  
    <property name="maxActive" value="${jdbc.maxActive}"></property>  
    <property name="maxWait" value="${jdbc.maxWait}"></property>  
    <property name="minIdle" value="${jdbc.minIdle}"></property>  
    <property name="driverClassName" value="${jdbc.driverClassName}"></property>  
    <property name="url" value="${jdbc.url}"></property>  
    <property name="username" value="${jdbc.username}"></property>  
    <property name="password" value="${jdbc.password}"></property>  
</bean>

        BeanFactoryPostProcessor就会对注册到BeanDefinationRegistry中的BeanDefination做最后的修改,替换$占位符为配置文件中的真实的数据。

        至此,整个容器启动阶段就算完成了,容器的启动阶段的最终产物就是注册到BeanDefinationRegistry中的一个个BeanDefination了,这就是Spring为Bean实例化所做的预热的工作。让我们再通过一张图简单回顾一下:

二、Bean的生成

        如果我们不是选择懒加载的方式,容器启动阶段完成之后,将立即启动Bean实例化阶段,通过隐式的调用所有依赖对象的getBean方法来实例化所有配置的Bean并保存起来。       

        而如果我们选择懒加载的方式,那么直到我们伸手向Spring要依赖对象实例之前,都是以BeanDefinationRegistry中一个个的BeanDefination的形式存在,也就是Spring只有在我们需要依赖对象的时候才进行相应对象的实例化。

        1. 生成BeanDefinition

        Spring启动的时候会进行扫描,会先调用org.springframework.context.annotation.ClassPathBeanDefinitionScanner#doScan()方法:

protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
		Assert.notEmpty(basePackages, "At least one base package must be specified");
		Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<>();
		for (String basePackage : basePackages) {
			// 根据扫描路径,得到BeanDefinition
			Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
			// 解析class
			for (BeanDefinition candidate : candidates) {
				ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
				candidate.setScope(scopeMetadata.getScopeName());
				String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
				if (candidate instanceof AbstractBeanDefinition) {
					postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
				}
				if (candidate instanceof AnnotatedBeanDefinition) {
					// 解析@lazy、@Primary、@DependsOn、@Role、@Description
					AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);
				}
				// 检查Spring容器是否已经存在beanName
				if (checkCandidate(beanName, candidate)) {
					BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
					definitionHolder =
							AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
					beanDefinitions.add(definitionHolder);
					// 注册
					registerBeanDefinition(definitionHolder, this.registry);
				}
			}
		}
		return beanDefinitions;
	}

扫描某个包路径,并得到BeanDefinition的Set集合。

扫描流程为:

  1. 通过ResourcePatternResolver获得指定包路径下的所有 .class 文件(Spring源码中将此文件包装成了Resource对象);
  2. 遍历每个Resource对象;
  3. 利用MetadataReaderFactory解析Resource对象得到MetadataReader(在Spring源码中MetadataReaderFactory具体的实现类为CachingMetadataReaderFactory,MetadataReader的具体实现类为SimpleMetadataReader);
  4. 利用MetadataReader进行excludeFilters和includeFilters,以及条件注解@Conditional的筛选(条件注解并不能理解:某个类上是否存在@Conditional注解,如果存在则调用注解中所指定的类的match方法进行匹配,匹配成功则通过筛选,匹配失败则pass掉。);
  5. 筛选通过后,基于metadataReader生成ScannedGenericBeanDefinition;
  6. 再基于metadataReader判断是不是对应的类是不是接口或抽象类;
  7. 如果筛选通过,那么就表示扫描到了一个Bean,将ScannedGenericBeanDefinition加入结果集。

        上面是说的通过扫描得到BeanDefinition对象,还可以通过直接定义BeanDefinition,或
解析spring.xml文件的<bean/>,或者@Bean注解得到BeanDefinition对象。

        2. 合并BeanDefinition

        通过扫描得到所有BeanDefinition之后,就可以根据BeanDefinition创建Bean对象了,但是在
Spring中支持父子BeanDefinition。

        父子BeanDefinition实际用的比较少,使用是这样的,比如:

<bean id="parent" class="com.zhouyu.service.Parent" scope="prototype"/>
<bean id="child" class="com.zhouyu.service.Child"/>

        这种情况下,child是单例Bean。

<bean id="parent" class="com.zhouyu.service.Parent" scope="prototype"/>
<bean id="child" class="com.zhouyu.service.Child" parent="parent"/>

        这种情况下,child就是原型Bean了。 因为child的父BeanDefinition是parent,所以会继承parent上所定义的scope属性。 
        而在根据child来生成Bean对象之前,需要进行BeanDefinition的合并,得到完整的child的
BeanDefinition(后面Bean的初始化源码中会提到)。

        3. 加载类

        BeanDefinition合并之后,就可以创建Bean对象了,而创建Bean须先实例化对象,而实例化就必须先加载当前BeanDefinition所对应的class,在AbstractAutowireCapableBeanFactory.
createBean()方法中,一开始就会调用:

Class<?> resolvedClass = resolveBeanClass(mbd, beanName);

        这行代码就是去加载类,该方法是这么实现的:

if (mbd.hasBeanClass()) {
  return mbd.getBeanClass();
}
if (System.getSecurityManager() != null) {
  return AccessController.doPrivileged((PrivilegedExceptionAction<Class<?>>) () ‐>
    doResolveBeanClass(mbd, typesToMatch), getAccessControlContext());
  }
else {
  return doResolveBeanClass(mbd, typesToMatch);
}

        进入hasBeanClass()方法:

public boolean hasBeanClass() {
  return (this.beanClass instanceof Class);
}

        如果beanClass属性的类型是Class,那么就直接返回,如果不是,则会根据类名进行加载
(doResolveBeanClass方法所做的事情)会利用BeanFactory所设置的类加载器来加载类,如果没有设置,则默认使用ClassUtils.getDefaultClassLoader()方法所返回的类加载器来加载。

        ClassUtils.getDefaultClassLoader()
        1. 优先返回当前线程中的ClassLoader;
        2. 线程中类加载器为null的情况下,返回ClassUtils类的类加载器;
        3. 如果ClassUtils类的类加载器为空,那么则表示是Bootstrap类加载器加载的ClassUtils类,则返回系统类加载器。

        4. 实例化前

        当前BeanDefinition对应的类成功加载后,就可以实例化对象了,但是在Spring中,实例化对象之前,Spring提供了一个扩展点,允许用户来控制是否在某个或某些Bean实例化之前做一些启动动作。这个扩展点叫InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation()。比如: 

@Component
public class IBeanPostProcessor implements InstantiationAwareBeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return null;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return null;
    }

    /**
     * 这个方法很重要,在spring中就是在这个方法里面处理@Autowired、@Resource、@Value注解
     * @param pvs
     * @param bean
     * @param beanName
     * @return
     * @throws BeansException
     */
    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        return null;
    }

    /**
     * 实例化之前调用的方法,传的参数不是对象(先看这个方法)
     */
    @SneakyThrows
    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if (beanName.equals("userService")) {
            System.out.println("实例化前");
        }
        return null;
    }
}

        在userService这个Bean实例化前,会进行打印。 
        值得注意的是,postProcessBeforeInstantiation()方法是有返回值的,如果按上面代码返回null,表示不需要Spring来实例化了,并且后续的Spring依赖注入也不会进行了,会跳过一些步骤,直接执行初始化后这一步。

       5. 实例化

        在这里就会根据BeanDefinition去创建对象了。会调用org.springframework.beans.factory.support.DefaultListableBeanFactory#preInstantiateSingletons()方法,先大致看一下:

	// 实例化方法
	@Override
	public void preInstantiateSingletons() throws BeansException {
		if (logger.isTraceEnabled()) {
			logger.trace("Pre-instantiating singletons in " + this);
		}

		// Iterate over a copy to allow for init methods which in turn register new bean definitions.
		// While this may not be part of the regular factory bootstrap, it does otherwise work fine.
		// 前面的registerBeanDefinition()方法会把所有的beanName缓存到这里
		List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);

		// Trigger initialization of all non-lazy singleton beans...
		// 在spring容器初始化时,遍历这个beanDefinitionNames,从这里拿beanDefinition的name
		for (String beanName : beanNames) {
			// 先合并BeanDefinition(如果存在parent,则合并父子BeanDefinition的属性,生成一个RootBeanDefinition)
			RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
			// 如果是单例的、非抽象的、非懒加载的就实例化
			if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
				// 判断bean是否实现FactoryBean接口
				if (isFactoryBean(beanName)) {
					// 获取FactoryBean对象,创建完之后放到单例池
					Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
					if (bean instanceof FactoryBean) {
						FactoryBean<?> factory = (FactoryBean<?>) bean;
						boolean isEagerInit;
						if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
							isEagerInit = AccessController.doPrivileged(
									(PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,
									getAccessControlContext());
						}
						else {
							// SmartFactoryBean继承FactoryBean接口,有个isEagerInit()方法设置是否容器启动就创建getObject()的实例
							isEagerInit = (factory instanceof SmartFactoryBean &&
									((SmartFactoryBean<?>) factory).isEagerInit());
						}
						if (isEagerInit) {
							// 创建真正的Bean对象(调用getObject()返回的对象)
							getBean(beanName);
						}
					}
				}
				else {
					// 再实例化(创建Bean对象)******
					getBean(beanName);
				}
			}
		}

		// Trigger post-initialization callback for all applicable beans...
		// 所有的非懒加载单例Bean都创建完之后
		for (String beanName : beanNames) {
			// 从单例池中拿beanName对应的单例Bean
			Object singletonInstance = getSingleton(beanName);
			if (singletonInstance instanceof SmartInitializingSingleton) {
				SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;
				if (System.getSecurityManager() != null) {
					AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
						smartSingleton.afterSingletonsInstantiated();
						return null;
					}, getAccessControlContext());
				}
				else {
					// 所有的单例Bean都创建完之后,才会调用每个单例Bean的该方法
					smartSingleton.afterSingletonsInstantiated();
				}
			}
		}
	}

        源码的详细解读会在后面的章节进行,本章先让大家有个初步的概念。

        6. BeanDefinition的后置处理

        Bean对象实例化出来之后,接下来就应该给对象的属性赋值了。在真正给属性赋值之前,Spring又提供了一个扩展点MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition(),可以对此时的
BeanDefinition进行加工,比如:

/**
 * @ClassName: MBeanPostProcessor
 * @Description: MergedBeanDefinitionPostProcessor接口的使用,会在Bean实例化时调用postProcessMergedBeanDefinition()方法
 * @Author: Kaisheng Du
 * @Date: 2021/9/25 10:35
 * @Version: 1.0
 */
@Component
public class MBeanPostProcessor implements MergedBeanDefinitionPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return null;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return null;
    }

    /**
     * 实例化时调用的方法
     */
    @Override
    public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
        if (beanName.equals("userService")) {
            // 指定BeanDefinition初始化时调用的方法(eg:调用test()方法)
            beanDefinition.setInitMethodName("test");
            // 在这里可以对BeanDefinition的属性进行赋值
            beanDefinition.getPropertyValues().add("student",new Student());
            // 指定销毁时执行的方法
            beanDefinition.setDestroyMethodName("close");
        }
    }
}

        在Spring源码中,AutowiredAnnotationBeanPostProcessor就是一个
MergedBeanDefinitionPostProcessor,它的postProcessMergedBeanDefinition()中会去查找注
入点,并缓存在AutowiredAnnotationBeanPostProcessor对象的一个Map中(injectionMetadataCache)。

        7.属性填充

        这个步骤中,就会处理@Autowired、@Resource、@Value等注解,也是通过
InstantiationAwareBeanPostProcessor.postProcessProperties()扩展点来实现的,比如我们
甚至可以实现一个自己的自动注入功能,比如:

@Component
public class KieasarInstantiationAwareBeanPostProcessor implements
InstantiationAwareBeanPostProcessor {
  @Override
  public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String
beanName) throws BeansException {
    if ("userService".equals(beanName)) {
      for (Field field : bean.getClass().getFields()) {
        if (field.isAnnotationPresent(ZhouyuInject.class)) {
          field.setAccessible(true);
          try {
            field.set(bean, "123");
          } catch (IllegalAccessException e) {
            e.printStackTrace();
          }
        }
      }
    }
    return pvs;
  }
}

关于@Autowired、@Resource、@Value的底层源码,会在后续的依赖注入过程中详解。

        8. 执行Aware

        完成了属性赋值之后,Spring会执行一些回调,包括:

  • BeanNameAware:回传beanName给bean对象;
  • BeanClassLoaderAware:回传classLoader给bean对象;
  • BeanFactoryAware:回传beanFactory给对象。

        这一步的实现是先检查相关的Aware接口,然后去Spring的对象池(也就是容器,也就是那个Map结构)中去查找相关的实例(例如对于ApplicationContextAware接口,就去找ApplicationContext实例),也就是说我们必须要在配置文件中或者使用注解的方式,将相关实例注册容器中,BeanFactory才可以为我们自动注入。

        而对于ApplicationContext,由于其本身继承了一系列的相关接口,所以当检测到Aware相关接口,需要相关依赖对象的时候,ApplicationContext完全可以将自身注入到其中,ApplicationContext实现这一步是通过下面要讲到的东东——BeanPostProcessor:

        例如,ApplicationContext继承自ResourceLoader和MessageSource,那么当我们实现ResourceLoaderAware和MessageSourceAware相关接口时,就将其自身注入到业务对象中即可。 

        9. 初始化前(BeanPostProcessor前置处理)

        初始化前,也是Spring提供的一个扩展点:
BeanPostProcessor.postProcessBeforeInitialization()方法,比如:

Component
public class ZhouyuBeanPostProcessor implements BeanPostProcessor {
  @Override
  public Object postProcessBeforeInitialization(Object bean, String beanName) throws
BeansException {
    if ("userService".equals(beanName)) {
      System.out.println("初始化前");
    }
    return bean;
  }
}

        BeanFactoryPostProcessor存在于容器启动阶段,而BeanPostProcessor存在于对象实例化阶段,BeanFactoryPostProcessor关注对象被创建之前那些配置的修修改改、缝缝补补,而BeanPostProcessor阶段关注对象已经被创建之后的功能增强,替换等操作,这样就很容易区分了。

        BeanPostProcessor与BeanFactoryPostProcessor都是Spring在Bean生产过程中强有力的扩展点。如果你还对它感到很陌生,那么你肯定知道Spring中著名的AOP(面向切面编程),其实就是依赖BeanPostProcessor对Bean对象功能增强的。

        BeanPostProcessor前置处理就是在要生产的Bean实例放到容器之前,允许我们程序员对Bean实例进行一定程度的修改、替换等操作。

        前面讲到的ApplicationContext对于Aware接口的检查与自动注入就是通过BeanPostProcessor实现的,在这一步Spring将检查Bean中是否实现了相关的Aware接口,如果是的话,那么就将其自身注入Bean中即可。Spring AOP就是在这一步实现的偷梁换柱,产生对于原生对象的代理对象,然后将对源对象上的方法调用,转而使用代理对象的相同方法调用实现的。

        利用初始化前,可以对进行了依赖注入的Bean进行处理:
        1. InitDestroyAnnotationBeanPostProcessor会在初始化前这个步骤中执行@PostConstruct的
方法,
        2. ApplicationContextAwareProcessor会在初始化前这个步骤中进行其他Aware的回调:
        i. EnvironmentAware:回传环境变量
        ii. EmbeddedValueResolverAware:回传占位符解析器
        iii. ResourceLoaderAware:回传资源加载器
        iv. ApplicationEventPublisherAware:回传事件发布器
        v. MessageSourceAware:回传国际化资源
        vi. ApplicationStartupAware:回传应用其他监听对象,可忽略
        vii. ApplicationContextAware:回传Spring容器ApplicationContext

        10. 初始化

        a. 查看当前Bean对象是否实现了InitializingBean接口,如果实现了就调用其afterPropertiesSet()方法;
        b. 执行BeanDefinition中指定的初始化方法。

        11.初始化后(BeanPostProcess后置处理)

        与前置处理类似,这里是在Bean自定义逻辑也执行完成之后,Spring又留给我们的最后一个扩展点。我们可以在这里在做一些我们想要的扩展。BeanPostProcessor.postProcessAfterInitialization(),比如:

@Component
public class ZhouyuBeanPostProcessor implements BeanPostProcessor {
  @Override
  public Object postProcessAfterInitialization(Object bean, String beanName) throws
BeansException {
    if ("userService".equals(beanName)) {
      System.out.println("初始化后");
    }
    return bean;
  }
}

        可以在这个步骤中,对Bean最终进行处理,Spring中的AOP就是基于初始化后实现的,初始化后返回的对象才是最终的Bean对象。

三、Bean的销毁

        Bean销毁是在Spring容器关闭过程中进行的。例如:

AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ScanBean.class);
UserService userService = (UserService) applicationContext.getBean("userService");
userService.test();
applicationContext.close();

        在Bean创建过程中,在最后(初始化之后),有一个步骤会去判断当前创建的Bean是不是
DisposableBean:

  1.  当前Bean是否实现了DisposableBean接口或当前Bean是否实现了AutoCloseable接口
  2. BeanDefinition中是否指定了destroyMethod
  3. 调用DestructionAwareBeanPostProcessor.requiresDestruction(bean)进行判断i. ApplicationListenerDetector中直接使得ApplicationListener是DisposableBeanii. InitDestroyAnnotationBeanPostProcessor中使得拥有@PreDestroy注解了的方法就是DisposableBean
  4. 把符合上述任意一个条件的Bean适配成DisposableBeanAdapter对象,并存入disposableBeans中(一个LinkedHashMap)   

        在 bean 创 建 完 成 后 就 会 对 这 个 bean 注 册 一 个 销 毁 的 Adapter 对 象 ,在doGetBean()中的registerDisposableBeanIfNecessary() 方法中 disposableBeans 集合负责对需要销毁的 bean 进行放置。

所属类:org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory

 /**
       * TODO Bean实例化+IOC依赖注入完成之后的调用,重要程度:5
       *     init-method属性和initializingBean接口方法afterPropertiesSet()调用,@PostConstruct注解方法调用,以及AOP代理对象的生成入口
       */
      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 {
      // 注册bean销毁时的类DisposableBeanAdapter
      registerDisposableBeanIfNecessary(beanName, bean, mbd);
   }
   catch (BeanDefinitionValidationException ex) {
      throw new BeanCreationException(
            mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
   }

   return exposedObject;
}

        registerDisposableBeanIfNecessary() 方法用来注册bean销毁时的类DisposableBeanAdapter,注册执行给定bean的所有销毁工作的DisposableBean实现:DestructionAwareBeanPostProcessors、DisposableBean接口、自定义销毁方法。

        DisposableBeanAdapter 对象就是负责 bean 销毁的类,这个类中收集 bean 是否实现了 DisposableBean 接口。

        其实对象的销毁与Spring关系不大,跟JVM有关,只是Spring在bean销毁前做一些事情,比如在容器销毁的时候释放一些资源等。

protected void registerDisposableBeanIfNecessary(String beanName, Object bean, RootBeanDefinition mbd) {
   AccessControlContext acc = (System.getSecurityManager() != null ? getAccessControlContext() : null);
   if (!mbd.isPrototype() && requiresDestruction(bean, mbd)) {
      if (mbd.isSingleton()) {
         // Register a DisposableBean implementation that performs all destruction
         // work for the given bean: DestructionAwareBeanPostProcessors,
         // DisposableBean interface, custom destroy method.
         // 注册执行给定bean的所有销毁工作的DisposableBean实现:DestructionAwareBeanPostProcessors、DisposableBean接口、自定义销毁方法。
         // 建立映射关系(beanName和DisposableBeanAdapter),注册bean销毁的类DisposableBeanAdapter,
         // 进入DisposableBeanAdapter-->
         registerDisposableBean(beanName, new DisposableBeanAdapter(
               // 重点看getBeanPostProcessorCache().destructionAware,BeanPostProcessor的应用
               bean, beanName, mbd, getBeanPostProcessorCache().destructionAware, acc));
      }
      else {
         // A bean with a custom scope...
         Scope scope = this.scopes.get(mbd.getScope());
         if (scope == null) {
            throw new IllegalStateException("No Scope registered for scope name '" + mbd.getScope() + "'");
         }
         scope.registerDestructionCallback(beanName, new DisposableBeanAdapter(
               bean, beanName, mbd, getBeanPostProcessorCache().destructionAware, acc));
      }
   }
}

进入registerDisposableBean() 方法,每一次bean的实例化在完成之后调用这个方法。

public void registerDisposableBean(String beanName, DisposableBean bean) {
   synchronized (this.disposableBeans) {
      // 建立映射关系
      this.disposableBeans.put(beanName, bean);
   }
}

进入DisposableBeanAdapter类的构造方法:

public DisposableBeanAdapter(Object bean, String beanName, RootBeanDefinition beanDefinition,
      List<DestructionAwareBeanPostProcessor> postProcessors, @Nullable AccessControlContext acc) {

   Assert.notNull(bean, "Disposable bean must not be null");
   this.bean = bean;
   this.beanName = beanName;
   this.invokeDisposableBean =
         // 看当前bean是否实现了DisposableBean接口
         (this.bean instanceof DisposableBean && !beanDefinition.isExternallyManagedDestroyMethod("destroy"));
   this.nonPublicAccessAllowed = beanDefinition.isNonPublicAccessAllowed();
   this.acc = acc;
   String destroyMethodName = inferDestroyMethodIfNecessary(bean, beanDefinition);
   if (destroyMethodName != null && !(this.invokeDisposableBean && "destroy".equals(destroyMethodName)) &&
         !beanDefinition.isExternallyManagedDestroyMethod(destroyMethodName)) {
      this.destroyMethodName = destroyMethodName;
      Method destroyMethod = determineDestroyMethod(destroyMethodName);
      if (destroyMethod == null) {
         if (beanDefinition.isEnforceDestroyMethod()) {
            throw new BeanDefinitionValidationException("Could not find a destroy method named '" +
                  destroyMethodName + "' on bean with name '" + beanName + "'");
         }
      }
      else {
         Class<?>[] paramTypes = destroyMethod.getParameterTypes();
         if (paramTypes.length > 1) {
            throw new BeanDefinitionValidationException("Method '" + destroyMethodName + "' of bean '" +
                  beanName + "' has more than one parameter - not supported as destroy method");
         }
         else if (paramTypes.length == 1 && boolean.class != paramTypes[0]) {
            throw new BeanDefinitionValidationException("Method '" + destroyMethodName + "' of bean '" +
                  beanName + "' has a non-boolean parameter - not supported as destroy method");
         }
         destroyMethod = ClassUtils.getInterfaceMethodIfPossible(destroyMethod);
      }
      this.destroyMethod = destroyMethod;
   }
   // 看filterPostProcessors()方法
   this.beanPostProcessors = filterPostProcessors(postProcessors, bean);
}

进入filterPostProcessors() 方法:

private List<DestructionAwareBeanPostProcessor> filterPostProcessors(
      List<DestructionAwareBeanPostProcessor> processors, Object bean) {

   List<DestructionAwareBeanPostProcessor> filteredPostProcessors = null;
   if (!CollectionUtils.isEmpty(processors)) {
      filteredPostProcessors = new ArrayList<>(processors.size());
      for (DestructionAwareBeanPostProcessor processor : processors) {
         if (processor.requiresDestruction(bean)) {
            // 过滤的PostProcessor就是CommonAnnotationBeanPostProcessor,因为这个类处理@PreDestroy注解
            filteredPostProcessors.add(processor);
         }
      }
   }
   return filteredPostProcessors;
}

我们看destroy() 方法:

所属类:org.springframework.beans.factory.support.DisposableBeanAdapter

public void destroy() {
   if (!CollectionUtils.isEmpty(this.beanPostProcessors)) {
      for (DestructionAwareBeanPostProcessor processor : this.beanPostProcessors) {
         // 调用到了InitDestroyAnnotationBeanPostProcessor中的该方法,这个类的子类就是CommonAnnotationBeanPostProcessor
         processor.postProcessBeforeDestruction(this.bean, this.beanName);
      }
   }

   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接口,调用destroy()
            ((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);
         }
      }
   }

   if (this.destroyMethod != null) {
      // 调用自定义的destroy-method方法
      invokeCustomDestroyMethod(this.destroyMethod);
   }
   else if (this.destroyMethodName != null) {
      Method methodToInvoke = determineDestroyMethod(this.destroyMethodName);
      if (methodToInvoke != null) {
         invokeCustomDestroyMethod(ClassUtils.getInterfaceMethodIfPossible(methodToInvoke));
      }
   }
}

自定义类实现DisposableBean接口,重写destroy() 方法:

@Component
public class DestoryBean implements DisposableBean {
    @Override
    public void destroy() throws Exception {
        System.out.println("==DestoryBean.destroy");
    }
}

另外,带注解@PreDestroy的方法:

@Component
public class PostConstructBean {

    @PreDestroy
    public void desy() {
        System.out.println("----desy");
    }
}

测试:

@Test
public void testDestroy() {
    ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
    applicationContext.getBeanFactory().destroyBean("jack");
    applicationContext.getBeanFactory().destroySingletons();
}

        Bean 是在什么时候被销毁呢,在 tomcat 关闭的时候就会调用到 servlet 中的销毁方法,具体是通过 ContextLoaderListener类中的 contextDestroyed 方法,通过 closeWebApplicationContext 方法一直往下找,此为 servlet 规范的使用,在这个方法中就会最终掉用到 DisposableBeanAdapter 类的 destroy()方法。

        在Spring容器关闭过程时:

        1. 首先发布ContextClosedEvent事件;
        2. 调用lifecycleProcessor的onCloese()方法;
        3. 销毁单例Bean:
                (1) 遍历disposableBeans;
                        a. 把每个disposableBean从单例池中移除;
                        b. 调用disposableBean的destroy()方法;
                        c. 如果这个disposableBean还被其他Bean依赖了,那么也得销毁其他Bean;
                        d. 如果这个disposableBean还包含了inner beans,将这些Bean从单例池中移除掉。
                (2)清空manualSingletonNames,是一个Set,存的是用户手动注册的单例Bean的
beanName;
                (3)清空allBeanNamesByType,是一个Map,key是bean类型,value是该类型所有的
beanName数组;
                (4)清空singletonBeanNamesByType,和allBeanNamesByType类似,只不过只存了单例Bean。

        Spring的Bean在为我们服务完之后,马上就要消亡了(通常是在容器关闭的时候),别忘了我们的自定义销毁逻辑,这时候Spring将以回调的方式调用我们自定义的销毁逻辑,然后Bean就这样走完了光荣的一生!

        我们再通过一张图来一起看一看Bean实例化阶段的执行顺序是如何的?

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值