Spring 容器的扩展点

Spring 容器的扩展点

Spring 为开发者预留了很多容器的扩展点,本文记录一下几个常用的扩展点的相关知识。

BeanFactoryPostProcessor

BeanFactoryPostProcessor 可以对 Bean 配置元信息进行操作,也就是说可以读取 BeanDefinition,并在 Bean 实例化之前进行修改。具体逻辑在下图的 3-5-1中。
annotationConfigApplicationContext-start

BeanDefinitionRegistryPostProcessor

BeanDefinitionRegistryPostProcessor 作为 BeanFactoryPostProcessor 的子接口额外提供了 postProcessBeanDefinitionRegistry 方法。

方法执行顺序

BeanFactoryPostProcessor
具体逻辑在 PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors 方法中。

FactoryBean

FactoryBean 主要用来定制化 Bean 的创建逻辑,提供了三个方法:

  • Object getObject():返回 FactoryBean 所创建的对象。
  • boolean isSingleton():返回 FactoryBean 所创建的对象是否为单例,默认返回 true。
  • Class getObjectType():返回 FactoryBean 所创建的对象的类型,如果我们能确认返回对象的类型的话,应该对该方法做出正确的实现,而不是返回 null。

注意点

  • 通过 FactoryBean.getBean(factoryBeanName) 方法返回的不是 FactoryBean 实例,而是 getObject() 方法创建的对象。想要获得 FactoryBean 实例需要在 factoryBeanName 前加 & 符号。
  • SmartFactoryBeanFactoryBean 的子接口,额外提供了 boolean isPrototype()boolean isEagerInit() 方法,默认都是返回 false。可以通过实现该接口并重写 isEagerInit 方法返回 true 达到在 Spring 容器启动时就执行 getObject 方法创建 Bean 的目的。

如何将一个对象交由 Spring 管理

Sring-Factory-Bean

Aware 接口

所有的 Aware 接口都是为了能让我们拿到容器中相关的资源,比如 BeanNameAware,可以让我们拿到 Bean 的名称,ApplicationContextAware 可以让我们拿到整个容器。

执行阶段

  • 第一阶段,执行 BeanXXXAware 接口;
AbstractAutowireCapableBeanFactory#initializeBean
   ...
   invokeAwareMethods(beanName, bean)

该阶段只有BeanNameAware,BeanClassLoaderAware,BeanFactoryAware 这三个接口会被执行。

  • 执行其他 Aware 接口
AbstractAutowireCapableBeanFactory#initializeBean
   ...
   applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName)

该阶段会执行其他 Aware 接口,不过是通过专门的后置处理器进行处理。例如 ApplicationContextAware 接口会被 ApplicationContextAwareProcessor 处理。并且这一步还会通过 CommonAnnotationBeanPostProcessor 后置处理器完成对 @PostConstructor 注解的处理, 注意 @PreDestroy @Resource 也是通过 CommonAnnotationBeanPostProcessor 处理的

LifeCycle

LifeCycle 顾名思义是一个生命周期,Spring 容器通过组合的方式持有一个 LifeCycleProcessor 实例,在容器启动和关闭的时候会回调当前容器中所有 LifeCycle 实例的 startstop 方法,其中 stop 方法只有在 isRunning 方法返回 true 的前提下才会生效。

AbstractApplicationContext#refresh
   ...
   finishRefresh()
      ...
      initLifecycleProcessor(); 
      getLifecycleProcessor().onRefresh();

具有依赖关系的 Bean 之间,例如 A 依赖了 B,那么 B.start 方法先于 A.start 执行,B.stop 方法晚于 A.stop 执行。

如果没有依赖关系的 Bean 之间要如何控制方法执行的先后顺序呢,可以通过继承 SmartLifeCycle 重写 getPhase() 方法,返回值越小 start 方法就越先执行,对应的 stop 方法就越晚执行。