Spring Aware 到底是什么?

通过如下前序两篇文章:
- Spring Bean 生命周期之“我从哪里来”?
- Spring Bean 生命周期之“我要到哪里去”?
我们了解了 Spring Bean 的生命周期核心内容,bean 是如何被初始化变为Ready for Use的状态,当资源被回收时又是如何被 destroy 的,但Spring Bean Life Cycle图并未被全部点亮,这篇文章将点亮剩余内容,同时说说你常见的 XxxxAware 接口
为什么要说 Spring Bean 生命周期又说 Aware 呢?下来点亮剩下内容你也许就明白了:

- 在 Spring Bean
Ready for Use之前的起源当然是要调用构造器,所以 Constructor 毋庸置疑是创建 Spring Bean 的第一步 - 通过 Setter 方法完成依赖注入,SDI (Setter Dependency Injection)
- 依赖注入一旦结束,
BeanNameAware.setBeanName()会被调用,它设置该 bean 在 Bean Factory 中的名称 - 接下来调用
BeanClassLoaderAware.setBeanClassLoader(),为 bean 实例提供类加载器,我们知道所有类都是要通过类加载器加载到上下文的,关于类的加载机制/双亲委派模型(大厂都爱问的面试题)内容会在后续给出来,让你透彻的了解 - 然后
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框架,但是希望看过本节内容之后阅读框架源码思维更加清晰
灵魂追问
- 框架中有哪些经典的 Aware 应用?
- 到现在你能很好的理解 Spring Bean 的生命周期吗?
Demo代码
涉及到 Spring Bean 生命周期的测试代码由于内容较多,没有写在此处,关注公众号并回复 「demo」获取相关代码,请自行尝试运行结果
提高效率工具

欢迎持续关注公众号:「日拱一兵」
- 前沿 Java 技术干货分享
- 高效工具汇总
- 面试问题分析与解答
- 技术资料领取
后续会出一系列文章点亮上图,同时进行 Spring 知识点解释与串联,在工作中充分利用 Spring 的特性
另外,还会推出 Java 多线程与 ElasticSearch 相关内容
持续关注,带你像读侦探小说一样轻松趣味学习 Java 技术栈相关知识

Spring Aware 到底是什么?的更多相关文章
- Spring知识点回顾(08)spring aware
Spring知识点回顾(08)spring aware BeanNameAware 获得容器中的bean名称 BeanFactoryAware 获得当前的bean factory Applicatio ...
- Spring Boot实战笔记(五)-- Spring高级话题(Spring Aware)
一.Spring Aware Spring 依赖注入的最大亮点就是你所有的 Bean 对 Spring容器的存在是没有意识的.即你可以将你的容器替换成其他的容器,如Google Guice,这时 Be ...
- spring boot到底帮我们做了那些事?
一.前言 上一篇介绍了注解,也是为这一篇做铺垫,传统的都是通过配置文件来启动spring,那spring boot到底是做了什么能让我们快速开发昵? 二.启动原理 看下程序启动的入口, ...
- Spring Aware容器感知技术
Spring Aware是什么 Spring提供Aware接口能让Bean感知Spring容器的存在,即让Bean可以使用Spring容器所提供的资源. Spring Aware的分类 几种常用的Aw ...
- spring boot: spring Aware的目的是为了让Bean获得Spring容器的服务
Spring Aware的目的是为了让Bean获得Spring容器的服务 //获取容器中的bean名称import org.springframework.beans.factory.BeanName ...
- Spring Aware
spring依赖注入的最大亮点就是所有的bean感知不到spring容器的存在,但在实际开发中,我们不可避免的要用到spring容器本身的功能资源,这时,我们就必须意识到容器的存在(废话,都要跟容器进 ...
- spring扩展点之四:Spring Aware容器感知技术,BeanNameAware和BeanFactoryAware接口,springboot中的EnvironmentAware
aware:英 [əˈweə(r)] 美 [əˈwer] adj.意识到的;知道的;觉察到的 XXXAware在spring里表示对XXX感知,实现XXXAware接口,并通过实现对应的set-XXX ...
- Spring Aware获取Bean和其他对象
Spring的容器托管了所有bean,实际项目中我们经常会用到容器中的功能资源,这时候就用到了 Spring Aware.简单来说,就是Spring Aware可以帮助你获取到Spring容器中的Be ...
- spring aware 的个人理解
今天学习到了spring aware ,特地百度了下这方面的知识,现在谈下我的理解. Spring的依赖注入的最大亮点就是你所有的Bean对Spring容器的存在是没有意识的.即你可以将你的容器替换成 ...
随机推荐
- Reverse Engineering Custom DataTypes -> GUID() in SQL Server to PostgreSQL
原文 https://archive.sap.com/discussions/thread/3641585 First you reverse engineer from a script where ...
- Android零基础入门第65节:RecyclerView分割线开发技巧
在上一期通过简单学习,已经领略到了RecyclerView的灵活性,当然都是一些最基础的用法,那么本期一起来学习RecyclerView的分割线使用. 相信有的比较细心的同学已经发现了,使用Recyc ...
- [机器学习]SVM原理
SVM是机器学习中神一般的存在,虽然自深度学习以来有被拉下神坛的趋势,但不得不说SVM在这个领域有着举足轻重的地位.本文从Hard SVM 到 Dual Hard SVM再引进Kernel Trick ...
- 为新项目添彩的 10+ 超有用 JavaScript 库
快速使用Romanysoft LAB的技术实现 HTML 开发Mac OS App,并销售到苹果应用商店中. <HTML开发Mac OS App 视频教程> 土豆网同步更新:http: ...
- qt开发的小软件,可以递归转换文件编码(qt为了防止内存泄露所做的保护机制)
应用场景 当你下载别人的源码的时候,而别人的源码跟你自己电脑里面的编码不一致的情况下将会出现乱码,但是如果要一个个转换编码的话那么那样所需要花的时间太多,所以就有必要写一个软件递归遍历项目下面所有的文 ...
- <iOS小技巧> 返回上级目录操作Goback()方法
Goback()方法功能:返回上一级界面,通过判断 popViewControllerAnimated 类型是否为空,来判断是present还是pop出来,然后直接做了releaseSelf操作: - ...
- 平衡二叉树 JAVA实现 亲测可用
平衡二叉树的JAVA实现 亲测可用 包括LL LR RL RR四种情况的旋转算法 以及添加删除树结点之后对平衡二叉树的维护算法 都已经实现并测试过 没有问题. 代码地址可以直接上我的GIT clone ...
- 解决vuejs 创建数据后设置对象的属性实现不了双向绑定问题
抛出踩坑:vue创建后的数据,自定义设置对象的属性,实现不了双向绑定 当业务场景,需要在请求接口数据新增自定义的属性 let foodList = [ {title: '回锅肉', price: 99 ...
- ajax中error函数参数与返回值详解 200 300 400 500
201-206:都表示服务器成功处理了请求的状态代码,说明网页可以正常访问. 200:(成功) 服务器已成功处理了请求.通常,这表示服务器提供了请求的网页. 201:(已创建) 请求成功且服务器已创建 ...
- 阿里云ECS发送企业邮件
<?phpuse PHPMailer\PHPMailer\PHPMailer;require '../vendor/autoload.php'; $mail = new PHPMailer(tr ...