Spring IOC 之深入分析 Aware 接口

 🎬作者简介:大家好,我是小徐🥇
☁️博客首页:CSDN主页小徐的博客
🌄每日一句:好学而不勤非真好学者

📜 欢迎大家关注! ❤️

AbstractAutowireCapableBeanFactory 的 #doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) 方法,主要干三件事情:

  1. 实例化 bean 对象:#createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) 方法。
  2. 属性注入:#populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) 方法。
  3. 初始化 bean 对象:#initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) 方法。

而初始化 bean 对象时,也是干了三件事情:

  1. 激活 Aware 方法
  2. 后置处理器的应用
  3. 激活自定义的 init 方法

这篇主要分析 Aware 接口。

1. Aware 接口

org.springframework.beans.factory.Aware 接口,定义如下:

/*** Marker superinterface indicating that a bean is eligible to be* notified by the Spring container of a particular framework object* through a callback-style method. Actual method signature is* determined by individual subinterfaces, but should typically* consist of just one void-returning method that accepts a single* argument.** <p>Note that merely implementing {@link Aware} provides no default* functionality. Rather, processing must be done explicitly, for example* in a {@link org.springframework.beans.factory.config.BeanPostProcessor BeanPostProcessor}.* Refer to {@link org.springframework.context.support.ApplicationContextAwareProcessor}* and {@link org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory}* for examples of processing {@code *Aware} interface callbacks.** @author Chris Beams* @since 3.1*/
public interface Aware {}

Aware 接口为 Spring 容器的核心接口,是一个具有标识作用的超级接口,实现了该接口的 bean 是具有被 Spring 容器通知的能力,通知的方式是采用回调的方式。

Aware 接口是一个空接口,实际的方法签名由各个子接口来确定,且该接口通常只会有一个接收单参数的 set 方法,该 set 方法的命名方式为 set + 去掉接口名中的 Aware 后缀,即 XxxAware 接口,则方法定义为 setXxx(),例如 BeanNameAware(setBeanName),ApplicationContextAware(setApplicationContext)。

Aware 的子接口需要提供一个 setXxx 方法,我们知道 set 是设置属性值的方法,即 Aware 类接口的 setXxx 方法其实就是设置 xxx 属性值的。 Aware 的含义是感知的、感应的,那么在 Spring 容器中是如何实现感知并设置属性值得呢?我们可以从初始化 bean 中的激活 Aware 的方法 #invokeAwareMethods(final String beanName, final Object bean) 中看到一点点,代码如下:

// AbstractAutowireCapableBeanFactory.javaprivate void invokeAwareMethods(final String beanName, final Object bean) {if (bean instanceof Aware) {// BeanNameAwareif (bean instanceof BeanNameAware) {((BeanNameAware) bean).setBeanName(beanName);}// BeanClassLoaderAwareif (bean instanceof BeanClassLoaderAware) {ClassLoader bcl = getBeanClassLoader();if (bcl != null) {((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);}}// BeanFactoryAwareif (bean instanceof BeanFactoryAware) {((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);}}
}
  • 首先,判断 bean 实例是否属于 Aware 接口的范畴,如果是的话,则调用实例的 setXxx() 方法给实例设置 xxx 属性值,在 #invokeAwareMethods(...) 方法,主要是设置 beanName,beanClassLoader、BeanFactory 中三个属性值。

2. Aware 子类

Spring 提供了一系列的 Aware 接口,如下图(部分):上面只是一部分子类,从这里我们可以看到 Spring 提供的 Aware 接口是是何其多。同时从上图我们也看到了几个比较熟悉的接口,如 BeanClassLoaderAware、BeanFactoryAware、BeanNameAware,下面就这三个接口来做一个简单的演示,先看各自的定义:

public interface BeanClassLoaderAware extends Aware {/*** 将 BeanClassLoader 提供给 bean 实例回调* 在 bean 属性填充之后、初始化回调之前回调,* 例如InitializingBean的InitializingBean.afterPropertiesSet()方法或自定义init方法*/void setBeanClassLoader(ClassLoader classLoader);}public interface BeanFactoryAware extends Aware {/*** 将 BeanFactory 提供给 bean 实例回调* 调用时机和 setBeanClassLoader 一样*/void setBeanFactory(BeanFactory beanFactory) throws BeansException;}public interface BeanNameAware extends Aware {/*** 在创建此 bean 的 bean工厂中设置 beanName*/void setBeanName(String name);}public interface ApplicationContextAware extends Aware {/*** 设置此 bean 对象的 ApplicationContext,通常,该方法用于初始化对象*/void setApplicationContext(ApplicationContext applicationContext)throws BeansException;}

2.1 示例

下面简单演示下上面四个接口的使用方法:

public class MyApplicationAware implements BeanNameAware,BeanFactoryAware,BeanClassLoaderAware,ApplicationContextAware{private String beanName;private BeanFactory beanFactory;private ClassLoader classLoader;private ApplicationContext applicationContext;@Overridepublic void setBeanClassLoader(ClassLoader classLoader) {System.out.println("调用了 BeanClassLoaderAware 的 setBeanClassLoader 方法");this.classLoader = classLoader;}@Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {System.out.println("调用了 BeanFactoryAware 的 setBeanFactory 方法");this.beanFactory = beanFactory;}@Overridepublic void setBeanName(String name) {System.out.println("调用了 BeanNameAware 的 setBeanName 方法");this.beanName = name;}@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {System.out.println("调用了 ApplicationContextAware 的 setApplicationContext 方法");this.applicationContext = applicationContext;}public void display(){System.out.println("beanName:" + beanName);System.out.println("是否为单例:" + beanFactory.isSingleton(beanName));System.out.println("系统环境为:" + applicationContext.getEnvironment());}
}

测试方法如下:

public static void main(String[] args) {ClassPathResource resource = new ClassPathResource("spring.xml");DefaultListableBeanFactory factory = new DefaultListableBeanFactory();XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);reader.loadBeanDefinitions(resource);MyApplicationAware applicationAware = (MyApplicationAware) factory.getBean("myApplicationAware");applicationAware.display();
}

运行结果:从该运行结果可以看出,这里只执行了三个 Aware 接口的 set 方法,原因就是通过 #getBean(...) 方法调用时,在激活 Aware 接口时只检测了 BeanNameAware、BeanClassLoaderAware、BeanFactoryAware 三个 Aware 接口。如果将测试方法调整为下面:

public static void main(String[] args) {ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");MyApplicationAware applicationAware = (MyApplicationAware) applicationContext.getBean("myApplicationAware");applicationAware.display();
}

则运行结果如下:

3. 总结

从本文我们基本上就可以 Aware 真正的含义是什么了?感知,其实是 Spring 容器在初始化主动检测当前 bean 是否实现了 Aware 接口,如果实现了则回调其 set 方法将相应的参数设置给该 bean ,这个时候该 bean 就从 Spring 容器中取得相应的资源。

最后文章末尾列出部分常用的 Aware 子接口,便于日后查询:

  • LoadTimeWeaverAware:加载Spring Bean时织入第三方模块,如AspectJ
  • BeanClassLoaderAware:加载Spring Bean的类加载器
  • BootstrapContextAware:资源适配器BootstrapContext,如JCA,CCI
  • ResourceLoaderAware:底层访问资源的加载器
  • BeanFactoryAware:声明BeanFactory
  • PortletConfigAware:PortletConfig
  • PortletContextAware:PortletContext
  • ServletConfigAware:ServletConfig
  • ServletContextAware:ServletContext
  • MessageSourceAware:国际化
  • ApplicationEventPublisherAware:应用事件
  • NotificationPublisherAware:JMX通知
  • BeanNameAware:声明Spring Bean的名字

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/669509.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

力扣分式化简

题目描述&#xff1a; 有一个同学在学习分式。他需要将一个连分数化成最简分数&#xff0c;你能帮助他吗&#xff1f; 连分数是形如上图的分式。在本题中&#xff0c;所有系数都是大于等于0的整数。 输入的cont代表连分数的系数&#xff08;cont[0]代表上图的a0&#xff0c;以…

Java学习-枚举类和泛型

1.枚举 什么是枚举类&#xff1f;格式是什么&#xff1f;&#xff1f; 枚举类的特点&#xff1a; 抽象枚举的注意点&#xff1a; 枚举的使用场景&#xff1a; 示例&#xff1a;枚举类对象作为参数传递 2.泛型 对泛型的认识&#xff1a; 自定义泛型类&#xff1a; 格式&#xff…

MySQL-运维-读写分离

一、介绍 二、一主一从读写分离 三、双主双从 1、介绍 2、准备 3、搭建 四、双主双从读写分离

“极简壁纸“爬虫JS逆向·实战

文章目录 声明目标分析确定目标目标检索 代码补全完整代码 爬虫逻辑完整代码 运行结果 声明 本教程只用于交流学习&#xff0c;不可用于商业用途&#xff0c;不可对目标网站进行破坏性请求&#xff0c;请遵守相关法律法规。 目标分析 确定目标 获取图片下载链接 目标检索…

OpenGL 入门(九)—Material(材质)和 光照贴图

文章目录 材质设置材质光的属性脚本实现 光照贴图漫反射贴图高光反射贴图 材质 材质本质是一个数据集&#xff0c;主要功能就是给渲染器提供数据和光照算法。 如果我们想要在OpenGL中模拟多种类型的物体&#xff0c;我们必须针对每种表面定义不同的材质(Material)属性。 我们…

【实训】自动运维ansible实训(网络管理与维护综合实训)

来自即将退役学长的分享&#xff0c;祝学弟学妹以后发大财&#xff01; 一 实训目的及意义 1.1 实训目的 1、熟悉自动化运维工具&#xff1a;实训旨在让学员熟悉 Ansible 这一自动化运维工具。通过实际操作&#xff0c;学员可以了解 Ansible 的基本概念、工作原理和使用方法…

Obsidian使用ddnsto穿透nas的webdav功能实现跨平台同步

之前一直用坚果云的webdav功能做obsidian的跨平台同步&#xff08;Windows&#xff0c;Ubuntu&#xff0c;iOS&#xff09;&#xff0c;但是今天在新的工作机上部署obsidian时&#xff0c;发现一次同步的文件数量超过了坚果云的限制&#xff08;付费用户好像是500次&#xff09…

springboot154基于Spring Boot智能无人仓库管理

简介 【毕设源码推荐 javaweb 项目】基于springbootvue 的 适用于计算机类毕业设计&#xff0c;课程设计参考与学习用途。仅供学习参考&#xff0c; 不得用于商业或者非法用途&#xff0c;否则&#xff0c;一切后果请用户自负。 看运行截图看 第五章 第四章 获取资料方式 **项…

2,cdc放缩位图

类似地&#xff0c;用pDC->StretchBlt来缩放&#xff0c;只是加上了两个参数&#xff0c;原始位图的宽高。 void CMy1_showbitmapView::StretchBitMap(CDC * pDC) { //CBitmap对象 CBitmap bitmap; //CDC对象 CDC dcMemory; //加载资源 bitmap.LoadBitmapW(IDB_BITMAP1); /…

基于单片机的智能寻光小车设计

摘 要&#xff1a;随着物联网技术的飞速发展和逐渐成熟&#xff0c;以单片机为主的智能小车在巡查、仓储、探险及国防等领域得到广泛应用。本文设计了一种基于单片机的智能寻光小车&#xff0c;该小车以STC89C52RC 芯片为设计核心&#xff0c;结合光敏传感器和超声波传感器等多…

leetcode(双指针)283.移动零(C++)DAY3

文章目录 1.题目示例提示 2.解答思路3.实现代码结果 4.总结 1.题目 给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。 示例 示例 1: 输入…

浅析软件测试中的一些常见理论:杀虫剂效应、金字塔模型、缺陷集群性原则、软件测试活动依赖于软件测试背景、软件测试的7大基本原则

这篇文章我主要想记录学习一下在软件测试行业中的一些常见理论效应以做基本了解。 一、杀虫剂效应 1、杀虫剂效应介绍 杀虫剂效应原本指农业中随着农药的普及使用&#xff0c;害虫对农药的抗药性就越来越强&#xff0c;农药就越来越难杀死害虫。在农场里为了对付破坏农作物的…

《爬虫职海录》卷二 • 爬在广州

HI&#xff0c;朋友们好&#xff0c;「爬虫职海录」第二期更新啦&#xff01; 本栏目的内容方向会以爬虫相关的“岗位分析”和“职场访谈”为主&#xff0c;方便大家了解一下当下的市场行情。 本栏目持续更新&#xff0c;暂定收集国内主要城市的爬虫岗位相关招聘信息&#xf…

SpringBoot注解--02---常用注解汇总

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 1.SpringBoot 配置启动注解SpringBootApplication 2.Bean处理注解2.1 依赖注入AutoWired、Qualifier、Resource 2.2 类被 Spring 容器创建&#xff0c;管理 iocComp…

我在代码随想录|写代码Day26 |回溯算法|332. 重新安排行程 , 51. N皇后 , 37. 解数独

学习目标&#xff1a; 博主介绍: 27dCnc 专题 : 数据结构帮助小白快速入门 &#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d;&#x1f44d; ☆*: .&#xff61;. o(≧▽≦)…

C++杂选

#include <iostream> #include <regex>using namespace std;int main() { //它声明了一个 string 类型的变量 input&#xff0c;用于存储输入的字符串。然后使用 getline() 函数从标准输入中读取一行输入&#xff0c;并将其存储在 input 变量中。string input;getl…

蓝桥杯Web应用开发-盒模型

盒模型 专栏持续更新中 盒子模型就是用来装 HTML 元素的盒子&#xff0c;它用于描述一个装有 HTML 元素的矩形盒子。该模型包括边框&#xff08;border&#xff09;、内边距&#xff08;padding&#xff09;、内容&#xff08;content&#xff09;、外边距&#xff08;margin…

《PCI Express体系结构导读》随记 —— 第II篇 第4章 PCIe总线概述(7)

接前一篇文章&#xff1a;《PCI Express体系结构导读》随记 —— 第II篇 第4章 PCIe总线概述&#xff08;6&#xff09; 4.1 PCIe总线的基础知识 与PCI总线不同&#xff0c;PCIe总线使用端到端的连接方式&#xff0c;在一条PCIe链路的两端只能各连接一个设备&#xff0c;这两个…

Springboot多种方法处理静态资源:设置并访问静态资源目录

&#xff5e;目录嗷&#xff5e; 静态文件application设置方法 配置详解编写配置优缺点 设置配置类方法 配置详解编写配置优缺点 总结 作者&#xff1a;Mintimate 博客&#xff1a;https://www.mintimate.cn Mintimate’s Blog&#xff0c;只为与你分享 静态文件 静态资源&…

DevOps落地笔记-15|混沌工程:通过问题注入提高系统可靠性

上一课时介绍了通过搭建一套部署流水线&#xff0c;高效、可靠的将软件部署到测试环境以及生产环境。到目前为止&#xff0c;我们学习了从用户需求到软件部署到生产环境交付给用户的全过程。随着软件工程不断发展&#xff0c;近几年&#xff0c;出现了一种新的实践&#xff0c;…