理解Spring Boot的ApplicationContextAwareProcessor:扩展点背后的魔法

ApplicationContextAwareProcessor#postProcessBeforeInitialization内部逻辑很简单,主要是执行了XxxAware相关扩展接口具体实现。
首页 新闻资讯 行业资讯 理解Spring Boot的ApplicationContextAwareProcessor:扩展点背后的魔法

前言

这篇文章主要来分享Springboot的扩展点之ApplicationContextAwareProcessor,而ApplicationContextAwareProcessor本身并不是扩展点,而是BeanPostProcessor扩展接口的具体实现,关于BeanPostProcessor扩展接口的功能特性、实现方式和工作原理可以移步Springboot扩展点之BeanPostProcessor,但是还是要当作Springboot的扩展点来分析,是因为其内部有6个扩展点可供实现,分别是EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware,这几个接口都是Spring预留的重点扩展实现,与Spring的Bean的生命周期密切相关。

功能特性

ApplicationContextAwareProcessor本身并不是扩展点,而是实现了BeanPostProcessor,并实现postProcessBeforeInitialization(),所以并不需要去实现它,但是其内部包含了以下6个接口实现的执行时机,这几个接口的功能作用分别是:

1、EnvironmentAware:用于获取Enviroment,Enviroment可以获得系统内的所有参数;另外也可以通过注入的方式来获得Environment,用哪种方式需要以实现场景而决定。

2、EmbeddedValueResolverAware:用于获取StringValueResolver,StringValueResolver可以获取基于String类型的properties的变量;另外还可以使用@Value的方式来获取properties的变量,用哪种方式需要以实现场景而决定。

3、ResourceLoaderAware:用于获取ResourceLoader,ResourceLoader可以用于获取classpath内所有的资源对象。

4、ApplicationEventPublisherAware:用于获取ApplicationEventPublisher,ApplicationEventPublisher可以用来发布事件,当然这个对象也可以通过spring注入的方式来获得,具体的实现方式可以参考Springboot事件监听机制的实战应用。

5、MessageSourceAware:用于获取MessageSource,MessageSource主要用来做国际化。

6、ApplicationContextAware:用来获取ApplicationContext,ApplicationContext就是Spring上下文管理器。

下面定义一个Bird类,实现ApplicationContextAware接口,以Bird为例分享ApplicationContextAwareProcessor的功能特性。

@Component@Slf4jpublicclass Bird implements ApplicationContextAware {
    private String name="xiao niao";private ApplicationContext applicationContext;@Overridepublicvoid setApplicationContext(ApplicationContext applicationContext)throws BeansException {
        this.applicationContext=applicationContext;log.info("----Spring的上下文环境application被注入");}
}
@Testpublicvoid test3(){
        log.info("----单元测试执行开始");AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext("com.fanfu");log.info("----单元测试执行完毕");}

单元测执行结果

图片图片

工作原理

注册时机

ApplicationContextAwareProcessor的注册时机,即准备BeanFactory的时候,注册的入口在AbstractApplicationContext#refresh----->AbstractApplicationContext#prepareBeanFactory方法中。

图片图片

执行逻辑

ApplicationContextAwareProcessor#postProcessBeforeInitialization的扩展逻辑很简单:即当前Bean是否实现了EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware,如果不是,则直拉返回,如果是,则执行XxxAware接口的扩展逻辑;

class ApplicationContextAwareProcessor implements BeanPostProcessor {
   private final ConfigurableApplicationContext applicationContext;private final StringValueResolver embeddedValueResolver;publicApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext){
      this.applicationContext=applicationContext;this.embeddedValueResolver=new EmbeddedValueResolver(applicationContext.getBeanFactory());}@Override@NullablepublicObject postProcessBeforeInitialization(Object bean,String beanName)throws BeansException {//如果非实现EnvironmentAware、EmbeddedValueResolverAware、//ResourceLoaderAware、ApplicationEventPublisherAware、//MessageSourceAware、ApplicationContextAware,则直拉返回;if(!(bean instanceof EnvironmentAware||bean instanceof EmbeddedValueResolverAware||bean instanceof ResourceLoaderAware||bean instanceof ApplicationEventPublisherAware||bean instanceof MessageSourceAware||bean instanceof ApplicationContextAware)){returnbean;}
      AccessControlContext acc=null;if(System.getSecurityManager()!=null){
         acc=this.applicationContext.getBeanFactory().getAccessControlContext();}if(acc!=null){
         AccessController.doPrivileged((PrivilegedAction<Object>)()->{
            invokeAwareInterfaces(bean);returnnull;},acc);}else{//如果实现XXXAware接口,则执行相关Aware接口的扩展方法;invokeAwareInterfaces(bean);}returnbean;}
   private void invokeAwareInterfaces(Object bean){if(bean instanceof EnvironmentAware){((EnvironmentAware)bean).setEnvironment(this.applicationContext.getEnvironment());}if(bean instanceof EmbeddedValueResolverAware){((EmbeddedValueResolverAware)bean).setEmbeddedValueResolver(this.embeddedValueResolver);}if(bean instanceof ResourceLoaderAware){((ResourceLoaderAware)bean).setResourceLoader(this.applicationContext);}if(bean instanceof ApplicationEventPublisherAware){((ApplicationEventPublisherAware)bean).setApplicationEventPublisher(this.applicationContext);}if(bean instanceof MessageSourceAware){((MessageSourceAware)bean).setMessageSource(this.applicationContext);}if(bean instanceof ApplicationContextAware){((ApplicationContextAware)bean).setApplicationContext(this.applicationContext);}
   }
}

执行时机

因为ApplicationContextAwareProcessor实现了BeanPostProcessor接口,并重写了postProcessBeforeInitialization()。关于BeanPostProcessor接口的执行时机可移步Springboot扩展点之BeanPostProcessor,这里就不再反复赘述了。

图片图片

总结

通过以上的分析,可以了解到:

1、ApplicationContextAwareProcessor实现BeanPostProcessor接口,是Spring扩展点之BeanPostProcessor的内部经典实现。

2、ApplicationContextAwareProcessor#postProcessBeforeInitialization内部逻辑很简单,主要是执行了XxxAware相关扩展接口具体实现;

3、ApplicationContextAwareProcessor注册时机相对比较早,即BeanFactory实例化后,相关属性初始化时;

4、ApplicationContextAwareProcessor#postProcessBeforeInitialization的执行时机,是在Spring管理的Bean实例化、属性注入完成后,InitializingBean#afterPropertiesSet方法以及自定义的初始化方法之前;

22    2023-12-05 07:48:23    Spring Boot