Spring中对Bean的创建到销毁的全过程都有非常完备的扩展点提供。
前言#
我们先来梳理下一个Bean是如何交给Spring管理的,先来简单提及下会涉及到的概念名词。
BeanFactory(Bean工厂,也就称作IoC容器),他就是整个Spring最核心的概念,所有Bean都是由他来管理,创造,销毁。
BeanDefinition(Bean定义),他是用来描述一个Bean的各种信息,BeanFactory就是根据BeanDefinition来去生成和创建Bean的,可以把他想象成施工的图纸,一切的一切都是根据图纸来的。Bean的元数据被存储在其中,如作用域,类名,属性值。
BeanFactoryPostProcessor(BeanFactory后处理器),他可以对BeanFactory进行功能的增强,如果BeanFactory想象成一个工厂车间,那BeanFactory后处理器就是额外的增强插件,可以给工厂添加新的功能。
BeanPostProcessor(Bean后处理器),他是对整个BeanFactory中的所有Bean都进额外的拓展,类似于将工厂流水线上的产品统一加上包装,或者让流水线上的产品生产前加点香料,让产品香气扑鼻(哈哈哈)。
Bean真正放到IoC容器中的产品,也就是我们大费周章想要得到的产品!
总览#
大致可以分成三个层次的扩展点,BeanFactory级,也就是对应BeanFactoryPostProcessor,对整个工厂进行额外拓展。Bean级,对应着BeanPostProcessor,对工厂内流水线上所有Bean都生效的拓展。具体Bean级,某个Bean单独声明了某些方法。
BeanFactory级#
为了更直观的感受整个级别能做的事情,我们先看点实际开发中已经在使用的功能,Spring框架自身就提供了许多的BeanFactoryPostProcessor帮助我们快速开发。
比如ConfigurationClassPostProcessor
用于处理@Configuration注解,PropertyPlaceholderConfigurer
用于处理属性占位符。可以跟随下面这段代码感受下。
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
//手动创建一个BeanDefinition
/**BeanDefinitionBuilder就是用来创造BeanDefinition的,在genericBeanDefinition中指明
想要创建的类是什么,然后可以用来链式调用去指明想要得到的BeanDefinition的一些属性,如名字,作用域,如何匹配参数(从IoC容器中),调用哪个构造器等等,然后得到你想要的BeanDefinition了。
*/
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder
.genericBeanDefinition(Config.class)
.setScope("singleton") .getBeanDefinition();
//将BeanDefinition注册进BeanFactory 但是你会发现,config类上的注解并没有被解析。
// 原因在于这些功能不是在BF上,而是在BF后处理器上。
beanFactory.registerBeanDefinition("config", beanDefinition);
//通过工具类给BF中添加BF后处理器
AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
//让BF执行这些后处理器
beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values()
.forEach( beanFactoryPostProcessor -> {
System.out.println(">>>>>>>>>>>>"+beanFactoryPostProcessor);
beanFactoryPostProcessor.postProcessBeanFactory(beanFactory);
});
不过我们应用层开发时,很少会注意到这些BeanFactoryPostProcessor的存在,因为他们本质上都是Spring在操作,我们拿到手上的是已经装配的后处理器的工厂。而下面的Bean级才是离我们开发更近的级别。
Bean级#
这一级别的拓展点相当的丰富,想要彻底搞清楚和理解有哪些拓展点。我们得想从Bean的生命周期开始说起,也可也移步参见我的另一篇博客。
Spring bean的生命周期大致可以分为四个阶段:
- 实例化(对应Java类实例化)
- 依赖注入(对应Java类设置字段值)
- 初始化(对应Java类调用init方法)
- 销毁(对应Java类调用destory方法)
Spring提供Bean级拓展点也是围绕着这四个状态展开的。
BeanPostProcessor
- 接口:
org.springframework.beans.factory.config.BeanPostProcessor
- 方法:
postProcessBeforeInitialization(Object bean, String beanName)
postProcessAfterInitialization(Object bean, String beanName)
这两个钩子方法分别是在实例化前和实例化后被调用。
InstantiationAwareBeanPostProcessor
- 接口:
org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor
- 继承:继承自
BeanPostProcessor
- 方法:
postProcessBeforeInstantiation(Class<?> beanClass, String beanName)
postProcessAfterInstantiation(Object bean, String beanName)
postProcessProperties(PropertyValues pvs, Object bean, String beanName)
这三个钩子方法,postProcessProperties
在依赖注入之前调用,postProcessBeforeInstantiation
在初始化前调用,postProcessAfterInstantiation
在初始化后调用。
DestructionAwareBeanPostProcessor
- 接口:
org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor
- 继承:继承自
BeanPostProcessor
- 方法:
postProcessBeforeDestruction(Object bean, String beanName)
这个钩子方法自然是在销毁之前调用。
理解了Bean的生命周期,就很轻松的能记住这个六个方法,分别是实例化前后共两个,依赖注入前一个,初始化前后共两个,销毁前一个。
需要特别留意的是,这个六个Bean级别的方法,是注册到BeanFactory上的,也就是说整个容器中所有的Bean生成时都会触发他们。
Bean自身的方法#
最后就是Bean自身的方法,大体上分为以下几类。
- 初始化方法:
@PostConstruct
、InitializingBean
的afterPropertiesSet()
、init-method
。 - 销毁方法:
@PreDestroy
、DisposableBean
的destroy()
、destroy-method
。 - 普通方法:通过Spring容器获取Bean实例后手动调用。
- 构造函数:在Bean实例化时调用。
- Setter方法:在依赖注入时调用。
最后#
整个流程可以参见这张图片~