• Spring钩子接口Aware


    前言

    我们在编写代码的时候,有的时候想要使用Spring的底层组件,类似于 ApplicationContext, BeanFactory等等

    那我们实现Spring提供的钩子方法xxxAware。在创建对象的时候,会调用接口规定的方法注入相关的组件。

    Aware接口

     1 /**
     2  * A marker superinterface indicating that a bean is eligible to be notified by the
     3  * Spring container of a particular framework object through a callback-style method.
     4  * The actual method signature is determined by individual subinterfaces but should
     5  * typically consist of just one void-returning method that accepts a single argument.
     6  *
     7  * <p>Note that merely implementing {@link Aware} provides no default functionality.
     8  * Rather, processing must be done explicitly, for example in a
     9  * {@link org.springframework.beans.factory.config.BeanPostProcessor}.
    10  * Refer to {@link org.springframework.context.support.ApplicationContextAwareProcessor}
    11  * for an example of processing specific {@code *Aware} interface callbacks.
    12  *
    13  * @author Chris Beams
    14  * @author Juergen Hoeller
    15  * @since 3.1
    16  */
    17 public interface Aware {}

    一个标记的超级接口,表明这个bean会被spring容器注意到,通过一个回调的风格。这个我也称之为钩子方法。

    我们可以看到如下图片,实现了Aware的接口的接口特别多,他们都是Spring自带的组件,我们通过Aware可以很方便的使用他们

    在此列举几个比较重要的接口,都是我经常用到的。

    Aware子接口描述  
    BeanNameAware 获取容器中 Bean 的名称  
    BeanFactoryAware 获取当前 BeanFactory ,这样可以调用容器的服务  
    ApplicationContextAware 注入IOC容器的,可以使用容器绝大部分功能
    MessageSourceAware 获取 Message Source 相关文本信息  
    EmbeddedValueResolverAware 值解析器,比如{}  #{}等等
    EnvironmentAware 环境解析器,可以拿properties的时候挺好用的

     

    ApplicationContextAware接口

     1 public interface ApplicationContextAware extends Aware {
     2 
     3     /**
     4      * Set the ApplicationContext that this object runs in.
     5      * Normally this call will be used to initialize the object.
     6      * <p>Invoked after population of normal bean properties but before an init callback such
     7      * as {@link org.springframework.beans.factory.InitializingBean#afterPropertiesSet()}
     8      * or a custom init-method. Invoked after {@link ResourceLoaderAware#setResourceLoader},
     9      * {@link ApplicationEventPublisherAware#setApplicationEventPublisher} and
    10      * {@link MessageSourceAware}, if applicable.
    11      * @param applicationContext the ApplicationContext object to be used by this object
    12      * @throws ApplicationContextException in case of context initialization errors
    13      * @throws BeansException if thrown by application context methods
    14      * @see org.springframework.beans.factory.BeanInitializationException
    15      */
    16     void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
    17 
    18 }

    这个可以获取Spring的IOC容器。拿到这个IOC容器,你可以拥有Spring的绝大多数功能。

    我们以ApplicationContextAware为例。直接继承XxxAware接口,就可以拿到他的相应字段了。

     1 @Component
     2 @Slf4j
     3 public class Person implements ApplicationContextAware, BeanFactoryAware,
     4         BeanNameAware, EnvironmentAware, EmbeddedValueResolverAware {
     5 
     6     @Override
     7     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
     8         log.info("applicationContext = {}", applicationContext.getBean("person"));
     9     }
    10 
    11     @Override
    12     public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
    13         log.info("beanFactory = {}", beanFactory.containsBean("person"));
    14     }
    15 
    16     @Override
    17     public void setBeanName(String name) {
    18         log.info("name = {}", name);
    19     }
    20 
    21     @Override
    22     public void setEmbeddedValueResolver(StringValueResolver resolver) {
    23         // 字符解析器
    24         log.info("val = {}", resolver.resolveStringValue("#{5 * 10}"));
    25     }
    26 
    27     @Override
    28     public void setEnvironment(Environment environment) {
    29         // 这个可以获取环境变量的值
    30         log.info("app = {}", environment.getProperty("app.secret"));
    31     }
    32 }

    结果:

    1 2020-04-04 21:35:39.474 [main] [] INFO  - [com.gdufe.osc.controller.Person java:37] [name = person]
    2 2020-04-04 21:35:39.475 [main] [] INFO  - [com.gdufe.osc.controller.Person java:32] [beanFactory = true]
    3 2020-04-04 21:35:39.475 [main] [] INFO  - [com.gdufe.osc.controller.Person java:48] [app = wenbochang888]
    4 2020-04-04 21:35:39.491 [main] [] INFO  - [com.gdufe.osc.controller.Person java:42] [val = 50]
    5 2020-04-04 21:35:39.493 [main] [] INFO  - [com.gdufe.osc.controller.Person java:27] [applicationContext = com.gdufe.osc.controller.Person@24386839]

    Aware接口底层实现原理

    我们看下如下的代码

     1 class ApplicationContextAwareProcessor implements BeanPostProcessor {
     2 
     3     @Override
     4     @Nullable
     5     public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
     6         
     7         .....
     8         invokeAwareInterfaces(bean);
     9         .....
    10 
    11         return bean;
    12     }
    13 
    14     private void invokeAwareInterfaces(Object bean) {
    15         if (bean instanceof Aware) {
    16             if (bean instanceof EnvironmentAware) {
    17                 ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
    18             }
    19             if (bean instanceof EmbeddedValueResolverAware) {
    20                 ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
    21             }
    22             if (bean instanceof ResourceLoaderAware) {
    23                 ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
    24             }
    25             if (bean instanceof ApplicationEventPublisherAware) {
    26                 ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
    27             }
    28             if (bean instanceof MessageSourceAware) {
    29                 ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
    30             }
    31             if (bean instanceof ApplicationContextAware) {
    32                 ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
    33             }
    34         }
    35     }
    36 }

    这里我稍微解释一下 BeanPostProcessor 方法。在初始化bean之前,以及之后,可以执行相应的方法。类似有点AOP的功能。

    那么ApplicationContextAwareProcessor 就很好理解了。

    在一个bean实例初始化之前调用postProcessBeforeInitialization方法。然后判断该bean有没有实现相应的aware接口,将对于的aware set进去即可,非常的方便。

  • 相关阅读:
    C语言-10-位域与共用体
    python-并发编程
    计算机操作系统
    网络编程-Socket
    网络编程-基础
    python-面向对象进阶
    python-面向对象
    python-模块分类与导入
    python-函数进阶
    python-函数内置方法
  • 原文地址:https://www.cnblogs.com/wenbochang/p/12634383.html
Copyright © 2020-2023  润新知