通过如下前序两篇文章:

  1. Spring Bean 生命周期之“我从哪里来”?
  2. Spring Bean 生命周期之“我要到哪里去”?
    我们了解了 Spring Bean 的生命周期核心内容,bean 是如何被初始化变为 Ready for Use 的状态,当资源被回收时又是如何被 destroy 的,但 Spring Bean Life Cycle图并未被全部点亮,这篇文章将点亮剩余内容,同时说说你常见的 XxxxAware 接口

为什么要说 Spring Bean 生命周期又说 Aware 呢?下来点亮剩下内容你也许就明白了:

  1. 在 Spring Bean Ready for Use之前的起源当然是要调用构造器,所以 Constructor 毋庸置疑是创建 Spring Bean 的第一步
  2. 通过 Setter 方法完成依赖注入,SDI (Setter Dependency Injection)
  3. 依赖注入一旦结束,BeanNameAware.setBeanName() 会被调用,它设置该 bean 在 Bean Factory 中的名称
  4. 接下来调用 BeanClassLoaderAware.setBeanClassLoader(),为 bean 实例提供类加载器,我们知道所有类都是要通过类加载器加载到上下文的,关于类的加载机制/双亲委派模型(大厂都爱问的面试题)内容会在后续给出来,让你透彻的了解
  5. 然后 BeanFactoryAware.setBeanFactory() 会被调用为 bean 实例提供其所拥有的 factory

关于 1、2 两点我要额外多说一些内容,请看下面代码:

这里,我们尝试通过构造器访问自动注入的 field Environment env,当构造器被调用时,Spring Bean 还没被完全初始化,这就会导致 NullPointerExceptions
我们变换一下方式:

这种方式,Environment 实例被安全注入之后才调用 @PostConstruct标记的方法,这样就不会抛出 NullPointerException 了。

这会回看周期图,有没有豁然开朗?

敲黑板

等所有 Spring Bean 都完成依赖注入(周期图中的 Setter Methods 部分)再使用 bean 的引用才是安全的方式,

后续会有一个章节专门说一说面试经常被问起的 Spring 有几种依赖注入方式的尴尬问题,请关注后续文章

到这里终于可以说一说 Aware 了,且看

Aware

Aware 翻译过来可以理解为"察觉的;注意到的;感知的" ,XxxxAware 也就是对....感知的,没有 Aware 就是无感知的吗?对喽

Spring 的依赖注入最大亮点就是所有的 Bean 对 Spring 容器的存在是没有意识的,拿 Spring Bean 生命周期之“我从哪里来”? 文章中“小学生入少先队”为例子说明,小学生还是那个小学生,加入少先队还是加入共青团只不过规则不一样罢了
但是在实际项目中,我们不可避免的要用到 Spring 容器本身提供的资源(难免要有事情需要少先队组织的帮助),这时候要让 Bean 主动意识到 Spring 容器的存在,才能调用 Spring 所提供的资源,这就是 Spring Aware. 其实 Spring Aware 是 Spring 设计为框架内部使用的,若使用了,你的 Bean 将会和 Spring 框架耦合,所以自己不单独使用,但是在读框架源码时希望你不再模糊.

常见的 Spring Aware 接口

Aware子接口 描述
BeanNameAware 获取容器中 Bean 的名称
BeanFactoryAware 获取当前 BeanFactory ,这样可以调用容器的服务
ApplicationContextAware 同上,在BeanFactory 和 ApplicationContext 的区别 中已明确说明
MessageSourceAware 获取 Message Source 相关文本信息
ApplicationEventPublisherAware 发布事件
ResourceLoaderAware 获取资源加载器,这样获取外部资源文件

来看类关系图:

当然不止以上这些 Aware, 通常使用 Spring Aware 的目的是为了让 Bean 获得 Spring 容器的服务。

代码示例

BeanNameAware

自定义 bean 实现 BeanNameAware

注册 bean

运行

和预想一样,Bean Name 输出结果为 myCustomBeanName,如果移除掉 @Bean 注解的 name 属性, 输出结果为 getMyBeanName

总结

在大多数情况下,我们应该避免使用任何 Aware 接口,除非我们需要它们。实现这些接口会将代码耦合到Spring框架,但是希望看过本节内容之后阅读框架源码思维更加清晰

灵魂追问

  1. 框架中有哪些经典的 Aware 应用?
  2. 到现在你能很好的理解 Spring Bean 的生命周期吗?

Demo代码

涉及到 Spring Bean 生命周期的测试代码由于内容较多,没有写在此处,关注公众号并回复 「demo」获取相关代码,请自行尝试运行结果


提高效率工具


欢迎持续关注公众号:「日拱一兵」

  • 前沿 Java 技术干货分享
  • 高效工具汇总
  • 面试问题分析与解答
  • 技术资料领取

后续会出一系列文章点亮上图,同时进行 Spring 知识点解释与串联,在工作中充分利用 Spring 的特性
另外,还会推出 Java 多线程与 ElasticSearch 相关内容

持续关注,带你像读侦探小说一样轻松趣味学习 Java 技术栈相关知识

Spring Aware 到底是什么?的更多相关文章

  1. Spring知识点回顾(08)spring aware

    Spring知识点回顾(08)spring aware BeanNameAware 获得容器中的bean名称 BeanFactoryAware 获得当前的bean factory Applicatio ...

  2. Spring Boot实战笔记(五)-- Spring高级话题(Spring Aware)

    一.Spring Aware Spring 依赖注入的最大亮点就是你所有的 Bean 对 Spring容器的存在是没有意识的.即你可以将你的容器替换成其他的容器,如Google Guice,这时 Be ...

  3. spring boot到底帮我们做了那些事?

    一.前言     上一篇介绍了注解,也是为这一篇做铺垫,传统的都是通过配置文件来启动spring,那spring boot到底是做了什么能让我们快速开发昵? 二.启动原理     看下程序启动的入口, ...

  4. Spring Aware容器感知技术

    Spring Aware是什么 Spring提供Aware接口能让Bean感知Spring容器的存在,即让Bean可以使用Spring容器所提供的资源. Spring Aware的分类 几种常用的Aw ...

  5. spring boot: spring Aware的目的是为了让Bean获得Spring容器的服务

    Spring Aware的目的是为了让Bean获得Spring容器的服务 //获取容器中的bean名称import org.springframework.beans.factory.BeanName ...

  6. Spring Aware

    spring依赖注入的最大亮点就是所有的bean感知不到spring容器的存在,但在实际开发中,我们不可避免的要用到spring容器本身的功能资源,这时,我们就必须意识到容器的存在(废话,都要跟容器进 ...

  7. spring扩展点之四:Spring Aware容器感知技术,BeanNameAware和BeanFactoryAware接口,springboot中的EnvironmentAware

    aware:英 [əˈweə(r)] 美 [əˈwer] adj.意识到的;知道的;觉察到的 XXXAware在spring里表示对XXX感知,实现XXXAware接口,并通过实现对应的set-XXX ...

  8. Spring Aware获取Bean和其他对象

    Spring的容器托管了所有bean,实际项目中我们经常会用到容器中的功能资源,这时候就用到了 Spring Aware.简单来说,就是Spring Aware可以帮助你获取到Spring容器中的Be ...

  9. spring aware 的个人理解

    今天学习到了spring aware ,特地百度了下这方面的知识,现在谈下我的理解. Spring的依赖注入的最大亮点就是你所有的Bean对Spring容器的存在是没有意识的.即你可以将你的容器替换成 ...

随机推荐

  1. [解决方案]sql server复制需要有实际的服务器名称才能连接到服务器

    原文:[解决方案]sql server复制需要有实际的服务器名称才能连接到服务器 在配置数据同步的时候,要求相互同步的两台机器的数据库必须通过默认实例名称进行连接.如果你的默认实例已经删掉了,在当前实 ...

  2. Android 联系人导入导出(VCard格式)

    之前在Android Contact 导入导出 vcf格式(不依赖第三方库)记录了一下依赖Android sdk中的功能导入导出联系人(第一次做java项目内容,有些地方的记录是否正确,暂时我也不知道 ...

  3. Android零基础入门第71节:CardView简单实现卡片式布局

    还记得我们一共学过了多少UI控件了吗?都掌握的怎么样啊. 安卓中一些常用控件学习得差不多了,今天再来学习一个新的控件CardView,在实际开发中也有非常高的地位. 一.CardView简介 Card ...

  4. .NET错误提示之:无法更新EntitySet“TableName”因为它有一个DefiningQuery

    使用LINQ 进行提交数据时发生的错误提示 原因:提交的对象表 没有设主键.

  5. Qt 开发WEB Services客户端代码(使用gSoap)

    1.   首先下载gSoap开发包 http://sourceforge.net/projects/gsoap2  目录包含 wsdl2h.exe( 由wsdl生成接口头文件C/C++格式的头文件 ) ...

  6. node应用远程调试教程

    远程调试 所谓远程调试,是指在本地IDE或命令行即时调试服务端代码,这在预发环境的测试阶段可以使用.远程调试避免了服务端环境的模拟,可快速定位bug. node应用调试 本文的教程主要针对采用 VS ...

  7. WCF学习--我的第一个WCF例子

    Windows Communication Foundation(WCF)是由微软发展的一组数据通信的应用程序开发接口,可以翻译为Windows通讯接口. 通信双方的沟通方式,由合约来订定.通信双方所 ...

  8. sublime3使用笔记

    1.ctrl+n 新建一个文件: 2.alt+shift+数字 分屏显示: 3.ctrl+alt+down(向下键) 连选很多行的指定开始位置: 如图: 紧接着再按shift+right(选中需要更改 ...

  9. python 方法无法在线程中使用(附python获取网络流量)

    在python中,定义一个方法,直接调用可以,但是创建一个线程来调用就可能导致失败.这种现象多出现在使用com对象进行系统操作时,而且是以线程的形式调用. 异常提示如下:syntax error.WM ...

  10. ABP开发框架前后端开发系列---(13)高级查询功能及界面的处理

    在一般的检索界面中,基于界面易用和美观方便的考虑,我们往往只提供一些常用的条件查询进行列表数据的查询,但是有时候一些业务表字段很多,一些不常见的条件可能在某些场景下也需要用到.因此我们在通用的查询条件 ...