Spring Aware 介紹

此次必定?
此次必定?

讀完這篇文章你將會收穫到web

  • Aware 的使用和介紹
  • BeanFactoryAware 的觸發時機
  • ApplicationContextAware 的觸發時機以及它經過擴展 BeanPostProcessor 來實現

咱們在 getBean 流程中曾經談到過 Spring 回調 Aware 接口緩存

private void invokeAwareMethods(final String beanName, final 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) {  ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);  }  }  } 複製代碼

咱們今天就來聊一下 Aware 接口app

public interface Aware {
 } 複製代碼

一個空的接口、啥都沒有、看註釋說它只是一個標誌性的接口、實現該接口的 bean 會被 Spring 以回調的方式進行通知、告訴你某個階段某件事情發生了編輯器

BeanNameAware

public interface BeanNameAware extends Aware {
 void setBeanName(String name); } 複製代碼

這個咱們舉兩個有意思的例子,一個是內部 bean 、一個是 factoryBean函數

<bean id="customer" class="com.demo.aware.Customer">
 <constructor-arg name="person">  <bean class="com.demo.aware.Person">  <property name="name" value="coderLi"/>  <property name="address" value="china"/>  <property name="age" value="666"/>  </bean>  </constructor-arg> </bean>  <bean id="cat" class="com.demo.aware.CatFactory"/> 複製代碼

具體的類就不貼了、沒啥邏輯、CatFactory 就實現了 Spring 提供的 FactoryBean 接口。而後咱們在 PersonCatFactory 中實現了接口 BeanNameAware 、並打印其參數 nameflex

Resource resource = new ClassPathResource("aware/coderLi.xml");
DefaultListableBeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory(); XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(defaultListableBeanFactory); xmlBeanDefinitionReader.loadBeanDefinitions(resource); defaultListableBeanFactory.getBean("customer"); defaultListableBeanFactory.getBean("cat"); 複製代碼

打印的結果就是:this

bean Name aware [bean Name is] :com.demo.aware.Person#71a794e5
bean Name aware [bean Name is] :cat 複製代碼

咱們打斷點在它們 getBean 以後,針對下面圖片的結果你是否有疑惑呢url

第一個是內部 bean Person 對象不在 Spring 的容器中、可是它卻觸發了 Aware 接口的回調 , 第二個是第一級緩存和 beanFactory 緩存中 key 都是 catspa

第一個問題其實很簡單、主要是構建 Customer 的構造函數的參數 Person 的時候、在 BeanDefinitionValueResolver#resolveInnerBean 中直接調用了 createBean 方法、而後就到了 doCreateBean 、以後就回調 Aware 接口、可是沒用放到 Spring 容器中3d

第二個問題、其實二者的 key 同樣是徹底沒有問題的、往前翻我分析 getBean 流程的文章能夠知道。這裏就不重複了

其餘

至於 BeanClassLoaderAwareBeanFactoryAware 就不演示代碼了、挺簡單的使用。

Spring 裏面比較常見的 Aware 接口

咱們看到不少像 ApplicationContextAware 或者 EnvironmentAwareAware 接口、並無在 invokeAwareMethods 中被調用到、由於其實這些都是在使用 ApplicationContext 的時候纔會被觸發的、具體是在哪裏被觸發調用呢?

咱們能夠看到 ApplicationContextAwareProcessor#invokeAwareInterfaces

中就寫了這麼一段代碼

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 的、

那這樣子的話就是在 doCreateBean 的時候、經過 initializeBean 進行回調了

那這個 ApplicationContextAwareProcessor 何時添加到 Spring 中啊

而這個方法則是在 refresh 方法中被調用了,而 refresh 的調用就不用介紹了把

public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
 this(new String[] {configLocation}, true, null); }  public ClassPathXmlApplicationContext(  String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)  throws BeansException {   super(parent);  setConfigLocations(configLocations);  if (refresh) {  refresh();  } } 複製代碼

其實 Spring 挺有意思的、將這個 ApplicationContextAwareProcessor 做爲其第一個 BeanPostProcessor 接口、那麼就能保證 Aware 接口被先回調、而後纔到用戶的 BeanPostProcessor 實現類

此次必定?
此次必定?
羣聊
羣聊
相關文章
相關標籤/搜索