Skip to main content

Spring中提供的拓展点

·113 words·1 min
glasscat
Author
glasscat
hi!
Table of Contents

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的生命周期大致可以分为四个阶段:

  1. 实例化(对应Java类实例化)
  2. 依赖注入(对应Java类设置字段值)
  3. 初始化(对应Java类调用init方法)
  4. 销毁(对应Java类调用destory方法)

Spring提供Bean级拓展点也是围绕着这四个状态展开的。

  1. BeanPostProcessor
  • 接口org.springframework.beans.factory.config.BeanPostProcessor
  • 方法
    • postProcessBeforeInitialization(Object bean, String beanName)
    • postProcessAfterInitialization(Object bean, String beanName)

这两个钩子方法分别是在实例化前和实例化后被调用。

  1. 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在初始化后调用。

  1. DestructionAwareBeanPostProcessor
  • 接口org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor
  • 继承:继承自BeanPostProcessor
  • 方法
    • postProcessBeforeDestruction(Object bean, String beanName)

这个钩子方法自然是在销毁之前调用。

理解了Bean的生命周期,就很轻松的能记住这个六个方法,分别是实例化前后共两个,依赖注入前一个,初始化前后共两个,销毁前一个。

需要特别留意的是,这个六个Bean级别的方法,是注册到BeanFactory上的,也就是说整个容器中所有的Bean生成时都会触发他们。

Bean自身的方法
#

最后就是Bean自身的方法,大体上分为以下几类。

  • 初始化方法@PostConstructInitializingBeanafterPropertiesSet()init-method
  • 销毁方法@PreDestroyDisposableBeandestroy()destroy-method
  • 普通方法:通过Spring容器获取Bean实例后手动调用。
  • 构造函数:在Bean实例化时调用。
  • Setter方法:在依赖注入时调用。

最后
#

整个流程可以参见这张图片~

image-20241229171612209