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 130 被围绕的区域
130. 被围绕的区域 给定一个二维的矩阵,包含 'X' 和 'O'(字母 O). 找到所有被 'X' 围绕的区域,并将这些区域里所有的 'O' 用 'X' 填充. 示例: X X X X X O O ...
- Java中lang包的常用方法介绍
JAVA API(图片来源:实验楼) 包装类 Integer包装类 方法 返回值 功能描述 byteValue() byte 以 byte 类型返回该 Integer 的值 intValue() in ...
- java计算时间从什么时候开始 为什么从1970年开始 java的时间为什么是一大串数字
Date date = new Date(0); System.out.println(date); 打印出来的结果: Thu Jan 01 08:00:00 CST 1970 也是1970 年 1 ...
- python3 修改计算机名称GUI程序
from tkinter import *from tkinter import messageboximport tkinterimport winregimport osdef serch(): ...
- dfs算法总结
DFS 深度优先搜索 主要有两种实现方法:栈和递归 什么是DFS?说白了就是一直遍历元素的方式而已,我们可以把它看成是一条小蛇,在每个分叉路口随意选择一条路线走,直到撞到南墙,才会调头返回到上一个分叉 ...
- Android开发之修改Manifest中meta-data的数据
代码 private void initFMMap() { ApplicationInfo appInfo = null; try { appInfo = this.getPackageManager ...
- Windows学习Nodejs、Npm和VUE
前言 本文主要以开发的角度讲解Node.js,Npm和Vue. Node.js学习 什么是Node.js Node.js简单来说就是一个IISExpress,提供一个前端Html的独立运行环境. 安装 ...
- RocketMQ系列(五)广播与延迟消息
今天要给大家介绍RocketMQ中的两个功能,一个是"广播",这个功能是比较基础的,几乎所有的mq产品都是支持这个功能的:另外一个是"延迟消费",这个应该算是R ...
- Java实现定时任务的三种简单方法
第一种方法: /** * 先定义一个任务每天执行的时间点,再写一个死循环,不断地拿当前时间和事先定义的时间去比对,若到时间则执行任务 */ @Test public void test1() { St ...
- 【转载】图解NumPy
目录 1. 读写文件 2. 内建向量/矩阵 3. 切片操作 4. 聚合函数 4.1. 向量 4.2. 矩阵 5. 矩阵的转置和重构 6. 常用操作API 7. 应用实例 7.1. 生成向量.矩阵 7. ...