引言

Spring中提供了各种Aware接口,方便从上下文中获取当前的运行环境,比较常见的几个子接口有:BeanFactoryAware,BeanNameAware,ApplicationContextAware,EnvironmentAware,BeanClassLoaderAware等,这些Aware的作用都可以从命名得知

Aware处理

其中BeanNameAwareBeanClassLoaderAwareBeanFactoryAware这三个是直接在bean的初始化之前就处理了的,具体代码在AbstractAutowireCapableBeanFactory.initializeBean方法中:

  1. protected Object initializeBean(String beanName, Object bean, RootBeanDefinition mbd) {
  2. // 判断对象实现的接口类型,处理特定的三种接口类型:BeanNameAware、BeanClassLoaderAware和BeanFactoryAware。
  3. if (bean instanceof BeanNameAware) {
  4. ((BeanNameAware) bean).setBeanName(beanName);
  5. }
  6. if (bean instanceof BeanClassLoaderAware) {
  7. ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
  8. }
  9. if (bean instanceof BeanFactoryAware) {
  10. ((BeanFactoryAware) bean).setBeanFactory(this);
  11. }
  12. // 开始Bean初始化前处理、初始化、初始化后处理
  13. Object wrappedBean = bean;
  14. if (mbd == null || !mbd.isSynthetic()) {
  15. wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
  16. }
  17. try {
  18. invokeInitMethods(beanName, wrappedBean, mbd);
  19. }
  20. catch (Throwable ex) {
  21. throw new BeanCreationException(
  22. (mbd != null ? mbd.getResourceDescription() : null),
  23. beanName, "Invocation of init method failed", ex);
  24. }
  25. if (mbd == null || !mbd.isSynthetic()) {
  26. wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
  27. }
  28. return wrappedBean;
  29. }

除了这三种之外的那些Aware接口的实现就不太一样了,它们都是利用BeanPostProcessor接口完成的,关于BeanPostProcessor接口的原理可以这篇文章:Spring扩展点之BeanPostProcessor

ApplicationContextAware就是利用ApplicationContextAwareProcessor实现的:

  1. public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
  2. AccessControlContext acc = null;
  3. if (System.getSecurityManager() != null &&
  4. (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
  5. bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
  6. bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
  7. acc = this.applicationContext.getBeanFactory().getAccessControlContext();
  8. }
  9. if (acc != null) {
  10. AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
  11. //具体实现
  12. invokeAwareInterfaces(bean);
  13. return null;
  14. }, acc);
  15. }
  16. else {
  17. //具体实现
  18. invokeAwareInterfaces(bean);
  19. }
  20. return bean;
  21. }
  22. private void invokeAwareInterfaces(Object bean) {
  23. if (bean instanceof Aware) {
  24. if (bean instanceof EnvironmentAware) {
  25. ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
  26. }
  27. if (bean instanceof EmbeddedValueResolverAware) {
  28. ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
  29. }
  30. if (bean instanceof ResourceLoaderAware) {
  31. ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
  32. }
  33. if (bean instanceof ApplicationEventPublisherAware) {
  34. ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
  35. }
  36. if (bean instanceof MessageSourceAware) {
  37. ((MessageSourceAware) bean).setMessageSource(this.applicationContext);
  38. }
  39. if (bean instanceof ApplicationContextAware) {
  40. ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
  41. }
  42. }
  43. }

ApplicationContextAwareProcessor的注册奥秘在AbstractApplicationContext.prepareBeanFactory方法中:

  1. beanFactory.setBeanClassLoader(getClassLoader());
  2. beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this));
  3. beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
  4. beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
  5. beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
  6. beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
  7. beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

Spring扩展点之Aware接口族的更多相关文章

  1. Spring扩展点之FactoryBean接口

    前言 首先看一下接口定义 public interface FactoryBean<T> { /** * 返回对象实例 */ @Nullable T getObject() throws ...

  2. spring源码:Aware接口(li)

    一.spring容器中的aware接口介绍 Spring中提供了各种Aware接口,比较常见的如BeanFactoryAware,BeanNameAware,ApplicationContextAwa ...

  3. spring源码:Aware接口

    一.spring容器中的aware接口介绍 Spring中提供了各种Aware接口,比较常见的如BeanFactoryAware,BeanNameAware,ApplicationContextAwa ...

  4. Spring扩展点-v5.3.9

    Spring 扩展点 **本人博客网站 **IT小神 www.itxiaoshen.com 官网地址****:https://spring.io/projects/spring-framework T ...

  5. Spring扩展之五:Aware接口等

    ApplicationContextAwareProcessor 1.介绍 ApplicationContextAwareProcessor是一个Spring内部工具,它实现了接口BeanPostPr ...

  6. Spring扩展点之BeanPostProcessor

    前言 BeanPostProcessor接口是Spring中一个非常重要的接口,它的接口定义如下 public interface BeanPostProcessor { Object postPro ...

  7. Spring扩展点之BeanFactoryPostProcessor

    前言 BeanFactoryPostProcessor接口是Spring中一个非常重要的接口,它的接口定义如下 public interface BeanFactoryPostProcessor { ...

  8. 手写Spring,定义标记类型Aware接口,实现感知容器对象

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 同事写的代码,我竟丝毫看不懂! 大佬的代码,就像 "赖蛤蟆泡青蛙,张的丑玩 ...

  9. spring扩展点之PropertyPlaceholderConfigurer

    原理机制讲解 https://leokongwq.github.io/2016/12/28/spring-PropertyPlaceholderConfigurer.html 使用时多个配置讲解 ht ...

随机推荐

  1. flask 基础2

    一.装饰器的坑 在使用装饰器函数时候,当一个装饰器装饰多个函数的时候,会由于内存地址相同时发生报错,因为装饰的都是一个函数 所以就需要引入 import functools  重新定义每一个函数的名称 ...

  2. Appium基础:Desired Capabilities详讲

    Desired Capabilities在启动session的时候是必须提供的,先看如下代码: Desired Capabilities本质上是key value的对象,他告诉appium serve ...

  3. Lodop打印表格带页头页尾 高度是否包含页头页尾 转载

    通过设置TableHeightScope,可以实现对ADD_PRINT_TABLE,表格带页头页尾,查看本博客另一篇博文:Lodop打印表格带页头页尾 自动分页每页显示头尾 超文本超过打印项高度,会自 ...

  4. tensorflow 待阅读的资料

    tensorflow性能调优实践 https://www.jianshu.com/p/937a0ce99f56 2018.04.01 Deep Learning 之 最优化方法 https://blo ...

  5. leetcode752. 打开转盘锁

    我们可以将 0000 到 9999 这 10000 状态看成图上的 10000 个节点,两个节点之间存在一条边,当且仅当这两个节点对应的状态只有 1 位不同,且不同的那位相差 1(包括 0 和 9 也 ...

  6. 求职-DB相关职位常见face题

    数据分析是个通用技能,适合各行各业,比如运营.产品.分析等职位都会要求会数据分析. 一.考察对数据分析岗位的理解与职业规划 数据分析师与数据工程师的区别在哪里? 为什么转行, 为什么没在公司内部转岗? ...

  7. arduino控制SIM900A模块

    https://item.taobao.com/item.htm?spm=a1z09.2.0.0.5fc02e8dncAF2p&id=604968021102&_u=i1qf7bf5f ...

  8. 2016年蓝桥别A组模拟训练

    1. 网友年龄 某君新认识一网友. 当问及年龄时,他的网友说: “我的年龄是个2位数,我比儿子大27岁, 如果把我的年龄的两位数字交换位置,刚好就是我儿子的年龄” 请你计算:网友的年龄一共有多少种可能 ...

  9. CF1136E Nastya Hasn't Written a Legend(线段树)

    还能说什么呢,简直太妙了. $$a_{i+1}<a_i+k_i$$ $$a_{i+1}-k_i-k_{i-1}-\cdots-k_1<a_i+k_i-k_i-k_{i-1}-\cdots- ...

  10. wifidog 用户第一次访问网络流程图

    通过wifidog实现用户上网强制认证后,用户第一次访问网络的流程大致如下: 1.用户通过浏览器访问某一网页. 2.wifidog重定向用户请求到认证服务器. 3.认证服务器返回登录认证页面给用户. ...