Spring已经成为了目前最流行的第三方开源框架之一,我们在充分享受Spring IOC容器带来的便捷时,也应该考虑一下Spring这个大工厂是如何将一个个的Bean生产出来的,我们一起来讨论一下Spring中Bean的生命周期。
Spring容器就好像生产车间的流水线,创建出来的对象就像是生产出来的一个个精美绝伦的产品。 Spring将管理的对象称之为Bean。
Spring最重要的功能就是帮助程序员创建对象(也就是IOC),而启动Spring就是为创建Bean对象做准备,所以我们先明白Spring到底是怎么去创建Bean的,也就是先弄明白Bean的生命周期。Bean的生命周期就是指:在Spring中,一个Bean是如何生成的,如何销毁的。
Bean的一生总体上来说可以分为三个阶段:
容器的启动阶段做了很多的预热工作,为后面Bean的实例化做好了充分的准备。
以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"));
}
在Java世界中,万物皆对象,散落于程序代码各处的注解以及保存在磁盘上的xml或者其他文件等等配置元信息,在内存中总要以一种对象的形式表示,就好比我们活生生的人对应到Java世界中就是一个Person类。
而Spring在内存中表示这些对象的方式就是BeanDefination,Bean对象被加载到内存之后是以BeanDefination的形式存在。
这样我们需要创建某一个对象实例的时候,找到相应的BeanDefination然后创建对象即可。那么我们需要某一个对象的时候,去哪里找到对应的BeanDefination呢?
通过Bean定义的id找到对象的BeanDefination的对应关系或者说映射关系又是如何保存的呢?这就引出了BeanDefinationRegistry了。
Spring通过BeanDefinationReader将对象加载到内存生成相应的BeanDefination之后,就将其注册到BeanDefinationRegistry中,BeanDefinationRegistry就是一个存放BeanDefination的大篮子,它也是一种键值对的形式,通过特定的Bean定义的id,映射到相应的BeanDefination。
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连接的时候可以这样配置:
BeanFactoryPostProcessor就会对注册到BeanDefinationRegistry中的BeanDefination做最后的修改,替换$占位符为配置文件中的真实的数据。
至此,整个容器启动阶段就算完成了,容器的启动阶段的最终产物就是注册到BeanDefinationRegistry中的一个个BeanDefination了,这就是Spring为Bean实例化所做的预热的工作。让我们再通过一张图简单回顾一下:
如果我们不是选择懒加载的方式,容器启动阶段完成之后,将立即启动Bean实例化阶段,通过隐式的调用所有依赖对象的getBean方法来实例化所有配置的Bean并保存起来。
而如果我们选择懒加载的方式,那么直到我们伸手向Spring要依赖对象实例之前,都是以BeanDefinationRegistry中一个个的BeanDefination的形式存在,也就是Spring只有在我们需要依赖对象的时候才进行相应对象的实例化。
Spring启动的时候会进行扫描,会先调用org.springframework.context.annotation.ClassPathBeanDefinitionScanner#doScan()方法:
protected Set doScan(String... basePackages) {
Assert.notEmpty(basePackages, "At least one base package must be specified");
Set beanDefinitions = new LinkedHashSet<>();
for (String basePackage : basePackages) {
// 根据扫描路径,得到BeanDefinition
Set 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集合。
扫描流程为:
上面是说的通过扫描得到BeanDefinition对象,还可以通过直接定义BeanDefinition,或
解析spring.xml文件的
通过扫描得到所有BeanDefinition之后,就可以根据BeanDefinition创建Bean对象了,但是在
Spring中支持父子BeanDefinition。
父子BeanDefinition实际用的比较少,使用是这样的,比如:
这种情况下,child是单例Bean。
这种情况下,child就是原型Bean了。 因为child的父BeanDefinition是parent,所以会继承parent上所定义的scope属性。
而在根据child来生成Bean对象之前,需要进行BeanDefinition的合并,得到完整的child的
BeanDefinition(后面Bean的初始化源码中会提到)。
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>) () ‐>
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类,则返回系统类加载器。
当前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依赖注入也不会进行了,会跳过一些步骤,直接执行初始化后这一步。
在这里就会根据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 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) ((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
源码的详细解读会在后面的章节进行,本章先让大家有个初步的概念。
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)。
这个步骤中,就会处理@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的底层源码,会在后续的依赖注入过程中详解。
完成了属性赋值之后,Spring会执行一些回调,包括:
这一步的实现是先检查相关的Aware接口,然后去Spring的对象池(也就是容器,也就是那个Map结构)中去查找相关的实例(例如对于ApplicationContextAware接口,就去找ApplicationContext实例),也就是说我们必须要在配置文件中或者使用注解的方式,将相关实例注册容器中,BeanFactory才可以为我们自动注入。
而对于ApplicationContext,由于其本身继承了一系列的相关接口,所以当检测到Aware相关接口,需要相关依赖对象的时候,ApplicationContext完全可以将自身注入到其中,ApplicationContext实现这一步是通过下面要讲到的东东——BeanPostProcessor:
例如,ApplicationContext继承自ResourceLoader和MessageSource,那么当我们实现ResourceLoaderAware和MessageSourceAware相关接口时,就将其自身注入到业务对象中即可。
初始化前,也是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
a. 查看当前Bean对象是否实现了InitializingBean接口,如果实现了就调用其afterPropertiesSet()方法;
b. 执行BeanDefinition中指定的初始化方法。
与前置处理类似,这里是在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销毁是在Spring容器关闭过程中进行的。例如:
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ScanBean.class);
UserService userService = (UserService) applicationContext.getBean("userService");
userService.test();
applicationContext.close();
在Bean创建过程中,在最后(初始化之后),有一个步骤会去判断当前创建的Bean是不是
DisposableBean:
在 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 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 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 filterPostProcessors(
List processors, Object bean) {
List 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
自定义类实现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实例化阶段的执行顺序是如何的?