Spring钩子接口Aware

前言

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

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

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容器注意到,经过一个回调的风格。这个我也称之为钩子方法。app

咱们能够看到以下图片,实现了Aware的接口的接口特别多,他们都是Spring自带的组件,咱们经过Aware能够很方便的使用他们ide

 

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

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的绝大多数功能。this

 

咱们以ApplicationContextAware为例。直接继承XxxAware接口,就能够拿到他的相应字段了。spa

 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 }

结果:code

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接口底层实现原理

咱们看下以下的代码orm

 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进去便可,很是的方便。

相关文章
相关标签/搜索