在 Spring 框架中有一个 org.springframework.beans.factory.Aware 接口,

Aware 是感知感应的意思,那么此接口的作用就是为 Spring 中的 bean 提供了感知外界的能力。

Aware接口本身只是一个标记接口,Spring 中提供了一系列具有具体感知能力的接口,它们都继承自 Aware 接口,

  部分如下:

  LoadTimeWeaverAware:加载 Spring Bean 时织入第三方模块,如AspectJ

  BeanClassLoaderAware:加载 Spring Bean 的类加载器

  BootstrapContextAware:资源适配器 BootstrapContext,如JCA,CCI

  ResourceLoaderAware:底层访问资源的加载器

  BeanFactoryAware:声明 BeanFactory

  PortletConfigAware:PortletConfig

  PortletContextAware:PortletContext

  ServletConfigAware:ServletConfig

  ServletContextAware:ServletContext

  MessageSourceAware:国际化

  ApplicationEventPublisherAware:应用事件

  NotificationPublisherAware:JMX通知

  BeanNameAware:声明 Spring Bean 的名字

  此处以 BeanNameAware 举例,其内部包含了一个 setBeanName 方法,所以当一个 bean 继承了此接口,并定义一个 beanName 的属性,

则在 Spring 容器初始化这个 bean 的时候,会调用这个 setBeanName 方法,注入这个 beanName。

  不同的 Aware 注入对应的外界信息的时机是不一样的,具体也分为两类:

  1. BeanNameAware/BeanClassLoaderAware/BeanFactoryAware

  这三类 Aware 生效的时机是在容器创建 bean 的最后一步完成,具体的调用顺序如下:

  getBean(String beanName)

    doGetBean(final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)

      getSingleton(String beanName, ObjectFactory<?> singletonFactory)

  在 getSingleton 会回调

  createBean(String beanName, RootBeanDefinition mbd, Object[] args)

    doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args)

      initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd)

  最终在 initializeBean 内会调用如下方法,此处分别调用了对应的 setXXX 方法,外部信息得以注入

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) {
((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}

  2. LoadTimeWeaverAware/ApplicationContextAware/ServletContextAware/MessageSourceAware 等

  这一类 Aware 是通过 BeanPostProcessor bean后置处理器实现外部信息注入的。

  同样在上述的 initializeBean 方法内会调用如下方法

public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException { Object result = existingBean;
for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
result = beanProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}

此处会调用容器中注册的所有的 BeanPostProcessor 的 postProcessBeforeInitialization 方法,而 ApplicationContextAwareProcessor 是默认注册到容器内的,其 postProcessBeforeInitialization 方法内会调用如下方法:

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);
}
}
}

所以 bean 只要继承了 EnvironmentAware,ResourceLoaderAware 就具备相应的感知能力。

最新文章

  1. fragment嵌套问题
  2. eclipse真机调试显示Target unknown的解决方法
  3. 利用vba将excel中的图片链接直接转换为图片
  4. iOS NSOperation的使用
  5. [转]Jexus的常用操作和基本配置
  6. C基础--函数指针的使用
  7. 彻底理解js中this的指向
  8. 监控Nginx负载均衡器脚本
  9. 给方法传递参数:ref参数和out参数
  10. css中margin:0 auto没作用
  11. HDU 1686 Oulipo(kmp)
  12. JS 经典代码段总结 start from 2016-08-22
  13. [LeetCode] Is Subsequence 题解
  14. MinGW下简单编译FFmpeg
  15. javascript this 的工作原理
  16. CSS之分组选择器和嵌套选择器
  17. [leetcode]149. Max Points on a Line多点共线
  18. Java(Java SE7) 体系结构图
  19. 使用TuShare下载历史逐笔成交数据并生成1分钟线
  20. WP8.1学习系列(第十九章)——事件和路由事件概述

热门文章

  1. Github上 10 个开源免费且优秀的后台控制面板
  2. 【K短路】牛慢跑
  3. IDEA 部署Tomcat教程(透彻理解操作)
  4. OsharpNS轻量级.net core快速开发框架简明入门教程-切换数据库(从SqlServer改为MySql)
  5. Airtest网易开源的一款UI自动化测试工具
  6. SpringBoot集成Spring Security(3)——异常处理
  7. spering getBean(),IOC
  8. linux安装go环境并编写第一个go程序
  9. scala高级部分--题目1
  10. docker容器中使用rsyslogd