什么是 Spring Aware?一篇文章快速上手并搞懂实现原理

什么是 Aware 接口

源码对Aware接口的注释是这样的:

A marker superinterface indicating that a bean is eligible to be notified by the Spring container of a particular framework object through a callback-style method. The actual method signature is determined by individual subinterfaces but should typically consist of just one void-returning method that accepts a single argument.

Aware 接口是「标记接口」,实现了 Aware 接口的 Bean,能够被 Spring 通过回调的方式,获取到一些与 Spring 容器相关的信息,比如 ApplicationContext,BeanFactory 等等。

说白了,想要让一个类获取 Spring 容器相关的信息,或者说持有 Spring 信息比如 ApplicationContext,这时候就得实现 Aware 接口了。

Aware 快速开始

这里以BeanFactoryAware为例:

 

java

复制代码

 @Component  public class TestAware implements BeanFactoryAware {  ​      private BeanFactory beanFactory;  ​      @Override      public void setBeanFactory(BeanFactory beanFactory) throws BeansException {          this.beanFactory = beanFactory;          System.out.println("Aware 接口调用 获取到 BeanFactory");     }  ​      public Object get(String name){          return beanFactory.getBean(name);     }  }

实现对应的 Aware 接口,就可以拿到对应的实例对象。

Aware 的实现原理

对于 Aware 接口,它本质是 A marker superinterface,是一个标记接口,熟悉 BeanPostProcessor 的同学们就有话要说了。

下面是 BeanPostProcessor 的 Javadoc:

Typically, post-processors that populate beans via marker interfaces or the like will implement postProcessBeforeInitialization

关注这几个词,populate beans via marker interfaces,是 通过标记接口填充bean 的意思,这不就是 Aware 接口吗。但根据 Aware 接口提供的信息不同,实现方式也会有所不同。

开始读源码

在 initializeBean 方法中,首先执行 invokeAwareMethods 方法。

 

java

复制代码

  protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {  ​          // 1. Aware   invokeAwareMethods(beanName, bean);  ​          // 2. BeanPostProcessorsBeforeInitialization   Object wrappedBean = bean;   if (mbd == null || !mbd.isSynthetic()) {   wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);   }  ​   // 3. InitMethods   invokeInitMethods(beanName, wrappedBean, mbd);          // 4. BeanPostProcessorsAfterInitialization   if (mbd == null || !mbd.isSynthetic()) {   wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);   }  ​   return wrappedBean;   }

invokeAwareMethods 会处理下面这几个 Aware 接口:

 

java

复制代码

 private void invokeAwareMethods(String beanName, Object bean) {     if (bean instanceof Aware) {        if (bean instanceof BeanNameAware) {           ((BeanNameAware) bean).setBeanName(beanName);       }        if (bean instanceof BeanClassLoaderAware) {           ClassLoader bcl = getBeanClassLoader();           if (bcl != null) {             ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);           }       }        if (bean instanceof BeanFactoryAware) {            // 回调 setBeanFactory           ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);       }     }  }

而在 applyBeanPostProcessorsBeforeInitialization 方法中,有这么几个 BeanPostProcessors:

image-20240214163346907

ApplicationContextAwareProcessor 长这样,这个类提供的是 embeddedValueResolver 和 ApplicationContext 相关信息:

 

java

复制代码

 /*  BeanPostProcessor implementation that supplies the ApplicationContext, Environment, or StringValueResolver for the ApplicationContext to beans that implement the EnvironmentAware, EmbeddedValueResolverAware, ResourceLoaderAware, ApplicationEventPublisherAware, MessageSourceAware, and/or ApplicationContextAware interfaces.  */  class ApplicationContextAwareProcessor implements BeanPostProcessor {  ​     private final ConfigurableApplicationContext applicationContext;           @Override     @Nullable     public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {        // 不需要回调的情况        if (!(... || bean instanceof ApplicationStartupAware)) {           return bean;       }        // 回调        invokeAwareInterfaces(bean);                return bean;     }       // 回调方法     private void invokeAwareInterfaces(Object bean) {   // ...        if (bean instanceof ApplicationContextAware) {           ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);       }     }  ​  }

而 WebApplicationContextServletContextAwareProcessor 提供的是 WebApplicationContextServletContext 相关信息,它的 Before 处理是这样的:

 

java

复制代码

 /*  Can be used when registering the processor can occur before the ServletContext or ServletConfig have been initialized.  */  @Override  public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {     if (getServletContext() != null && bean instanceof ServletContextAware) {       ((ServletContextAware) bean).setServletContext(getServletContext());     }     if (getServletConfig() != null && bean instanceof ServletConfigAware) {       ((ServletConfigAware) bean).setServletConfig(getServletConfig());     }     return bean;  }

  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值