Spring Aware介绍
读完这篇文章你将会收获到
Aware
的使用和介绍BeanFactoryAware
的触发时机ApplicationContextAware
的触发时机以及它通过扩展BeanPostProcessor
来实现
我们在 getBean
流程中曾经谈到过 Spring
回调 Aware
接口
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) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
}
}
我们今天就来聊一下 Aware
接口
public interface Aware {
}
一个空的接口、啥都没有、看注释说它只是一个标志性的接口、实现该接口的 bean
会被 Spring
以回调的方式进行通知、告诉你某个阶段某件事情发生了
BeanNameAware
public interface BeanNameAware extends Aware {
void setBeanName(String name);
}
这个我们举两个有意思的例子,一个是内部 bean
、一个是 factoryBean
<bean id="customer" class="com.demo.aware.Customer">
<constructor-arg name="person">
<bean class="com.demo.aware.Person">
<property name="name" value="coderLi"/>
<property name="address" value="china"/>
<property name="age" value="666"/>
</bean>
</constructor-arg>
</bean>
<bean id="cat" class="com.demo.aware.CatFactory"/>
具体的类就不贴了、没啥逻辑、CatFactory
就实现了 Spring
提供的 FactoryBean
接口。然后我们在 Person
和 CatFactory
中实现了接口 BeanNameAware
、并打印其参数 name
Resource resource = new ClassPathResource("aware/coderLi.xml");
DefaultListableBeanFactory defaultListableBeanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(defaultListableBeanFactory);
xmlBeanDefinitionReader.loadBeanDefinitions(resource);
defaultListableBeanFactory.getBean("customer");
defaultListableBeanFactory.getBean("cat");
打印的结果就是:
bean Name aware [bean Name is] :com.demo.aware.Person#71a794e5
bean Name aware [bean Name is] :cat
我们打断点在它们 getBean
之后,针对下面图片的结果你是否有疑惑呢
第一个是内部 bean
Person
对象不在 Spring
的容器中、但是它却触发了 Aware
接口的回调 , 第二个是第一级缓存和 beanFactory
缓存中 key
都是 cat
第一个问题其实很简单、主要是构建 Customer
的构造函数的参数 Person
的时候、在 BeanDefinitionValueResolver#resolveInnerBean
中直接调用了 createBean
方法、然后就到了 doCreateBean
、之后就回调 Aware
接口、但是没用放到 Spring
容器中
第二个问题、其实两者的 key
一样是完全没有问题的、往前翻我分析 getBean
流程的文章可以知道。这里就不重复了
其他
至于 BeanClassLoaderAware
和 BeanFactoryAware
就不演示代码了、挺简单的使用。
Spring
里面比较常见的 Aware
接口
我们看到很多像 ApplicationContextAware
或者 EnvironmentAware
的 Aware
接口、并没有在 invokeAwareMethods
中被调用到、因为其实这些都是在使用 ApplicationContext
的时候才会被触发的、具体是在哪里被触发调用呢?
我们可以看到 ApplicationContextAwareProcessor#invokeAwareInterfaces
中就写了这么一段代码
private void invokeAwareInterfaces(Object bean) {
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
实现了 BeanPostProcessor
的、
那这样子的话就是在 doCreateBean
的时候、通过 initializeBean
进行回调了
那这个 ApplicationContextAwareProcessor
什么时候添加到 Spring
中啊
而这个方法则是在 refresh
方法中被调用了,而 refresh
的调用就不用介绍了把
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[] {configLocation}, true, null);
}
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
throws BeansException {
super(parent);
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
其实 Spring
挺有意思的、将这个 ApplicationContextAwareProcessor
作为其第一个 BeanPostProcessor
接口、那么就能保证 Aware
接口被先回调、然后才到用户的 BeanPostProcessor
实现类
Spring Aware介绍的更多相关文章
- Spring Batch 中文参考文档 V3.0.6 - 1 Spring Batch介绍
1 Spring Batch介绍 企业领域中许多应用系统需要采用批处理的方式在特定环境中运行业务操作任务.这种业务作业包括自动化,大量信息的复杂操作,他们不需要人工干预,并能高效运行.这些典型作业包括 ...
- [翻译]Spring框架参考文档(V4.3.3)-第二章Spring框架介绍 2.1 2.2 翻译--2.3待继续
英文链接:http://docs.spring.io/spring-framework/docs/current/spring-framework-reference/html/overview.ht ...
- 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 的介绍和目标
1. Spring介绍 打开Spring 官网查看对 Spring 的介绍和目标 http://www.springsource.org/about We believe that: · J2EE s ...
- Spring的介绍与搭建
一.Spring的介绍 二.Spring的搭建 (1)导包 (2)创建一个对象 (3)书写配置注册对象到容器 (4)代码测试
- Spring Shell介绍
最近开发中在下遇到了spring-shell开发工具的项目,现在整理了相关文章,以供大家学习 本博客相关的文章均是在Spring Shell 1.2.0的基础上建立 Spring Shell介绍 ...
- Spring DevTools 介绍
Spring DevTools 介绍 Spring Boot包括一组额外的工具,可以使应用程序开发体验更加愉快. spring-boot-devtools模块可以包含在任何项目中,它可以节省大量的时间 ...
- Spring Aware容器感知技术
Spring Aware是什么 Spring提供Aware接口能让Bean感知Spring容器的存在,即让Bean可以使用Spring容器所提供的资源. Spring Aware的分类 几种常用的Aw ...
随机推荐
- Java实现 LeetCode 149 直线上最多的点数
149. 直线上最多的点数 给定一个二维平面,平面上有 n 个点,求最多有多少个点在同一条直线上. 示例 1: 输入: [[1,1],[2,2],[3,3]] 输出: 3 解释: ^ | | o | ...
- java实现欧拉与鸡蛋
** 欧拉与鸡蛋** 大数学家欧拉在集市上遇到了本村的两个农妇,每人跨着个空篮子.她们和欧拉打招呼说两人刚刚卖完了所有的鸡蛋. 欧拉随便问:"卖了多少鸡蛋呢?" 不料一个说:&qu ...
- python IDE pycharm的安装与使用
Python开发最牛逼的IDE——pycharm (其实其它的工具,例如eclipse也可以写,只不过比较麻烦,需要安装很多的插件,所以说pycharm是最牛逼的) pycharm,下载专业版的,不要 ...
- TCP协议“三次握手”与“四次挥手”详解(下)
前面进行“三次握手”建立连接后,当客户端的数据发送完毕,它就会要求与服务器端断开连接,那么就要进行“四次挥手”进行连接的释放. 注意,此处所谓的“客户端”与“服务器端”,只是为了方便标识连接的双方,即 ...
- Flutter 中 GestureDetector 的使用误区
在实际开发中,我们通常需要实现某个组件的更多点击事件.比如:原生的RaisedButton组件是无法响应诸如拖拽或是按下.抬起等细化的动作,它只有一个onPressed()方法来表示.当我们想实现这些 ...
- VSCode最佳设置
最近在学习Vue,用VSCode开发.经过摸索,VSCode最佳设置. { "eslint.enable": false, "workbench.colorTheme&q ...
- boost常用库(一):boost数值转换
在STL中有一些字符转换函数,例如atoi,itoa等,在boost里面只需用一个函数lexical_cast进行转换,lexical_cast是模板方法,使用时需要传入类型.只能是数值类型转字符串. ...
- jenkins环境安装(windows)
一.简介 Jenkins是一个开源软件项目,是基于Java开发的一种持续集成工具,用于监控持续重复的工作,旨在提供一个开放易用的软件平台,使软件的持续集成变成可能. 二. Jenkins功能 1. ...
- 让LED程序在片外SDRAM中运行
让LED程序在片外SDRAM中运行 一.引子 在前一篇文章中,我们已经成功点亮过LED了,为什么还要再重复一次呢? 我们已经知道,Mini2440开发板有两种启动模式:从NorFlash启动和从Nan ...
- [LOJ#500]「LibreOJ β Round」ZQC的拼图
题目 点这里看题目. 分析 首先不难发现答案具有单调性,因此可以二分答案.答案上限为\(V=2m\times \max\{a_i, b_i\}\). 考虑如何去判断当前的答案.设这个答案为 ...