Spring擴展點之Aware介面族

  • 2019 年 10 月 4 日
  • 筆記

Spring中提供了各種Aware介面,方便從上下文中獲取當前的運行環境,比較常見的幾個子介面有:BeanFactoryAware,BeanNameAware,ApplicationContextAware,EnvironmentAware,BeanClassLoaderAware等

這些Aware的作用都可以從命名得知

Aware的處理

其中BeanNameAwareBeanClassLoaderAwareBeanFactoryAware這三個是直接在bean的初始化之前就處理了的,具體程式碼在AbstractAutowireCapableBeanFactory.initializeBean方法中:

protected Object initializeBean(String beanName, Object bean, RootBeanDefinition mbd) {      // 判斷對象實現的介面類型,處理特定的三種介面類型:BeanNameAware、BeanClassLoaderAware和BeanFactoryAware。      if (bean instanceof BeanNameAware) {          ((BeanNameAware) bean).setBeanName(beanName);      }        if (bean instanceof BeanClassLoaderAware) {          ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());      }        if (bean instanceof BeanFactoryAware) {          ((BeanFactoryAware) bean).setBeanFactory(this);      }      // 開始Bean初始化前處理、初始化、初始化後處理      Object wrappedBean = bean;      if (mbd == null || !mbd.isSynthetic()) {          wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);      }        try {          invokeInitMethods(beanName, wrappedBean, mbd);      }      catch (Throwable ex) {          throw new BeanCreationException(                  (mbd != null ? mbd.getResourceDescription() : null),                  beanName, "Invocation of init method failed", ex);      }        if (mbd == null || !mbd.isSynthetic()) {          wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);      }      return wrappedBean;  }

除了這三種之外的那些Aware介面的實現就不太一樣了,它們都是利用BeanPostProcessor介面完成的,關於BeanPostProcessor介面的原理可以這篇文章:Spring擴展點之BeanPostProcessor

ApplicationContextAware就是利用ApplicationContextAwareProcessor實現的:

public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {      AccessControlContext acc = null;        if (System.getSecurityManager() != null &&          (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||              bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||              bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {        acc = this.applicationContext.getBeanFactory().getAccessControlContext();      }        if (acc != null) {        AccessController.doPrivileged((PrivilegedAction<Object>) () -> {          //具體實現          invokeAwareInterfaces(bean);          return null;        }, acc);      }      else {                //具體實現        invokeAwareInterfaces(bean);      }        return bean;    }  private void invokeAwareInterfaces(Object bean) {      if (bean instanceof Aware) {        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的註冊奧秘在AbstractApplicationContext.prepareBeanFactory方法中:

beanFactory.setBeanClassLoader(getClassLoader());  beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this));  beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));  beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);  beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);  beanFactory.ignoreDependencyInterface(MessageSourceAware.class);  beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);