Spring揭秘:Aware接口应用场景及实现原理!

内容概要
Aware接口赋予了Bean更多自感知的能力,通过实现不同的Aware接口,Bean可以轻松地获取到Spring容器中的其他资源引用,像ApplicationContext、BeanFactory等。
这样不仅增强了Bean的功能,还提高了代码的可维护性和扩展性,从而让Spring的IoC容器变得更加强大和灵活。
核心概念
它能解决什么问题?
在Spring中,Aware接口是一种标记接口,它本身并没有定义任何方法,但是Spring提供了一系列以Aware命名的接口,如BeanNameAware、BeanFactoryAware、ApplicationContextAware等。
这些接口定义了一些回调方法,通过这些回调方法,Spring容器在初始化Bean时会将容器中的一些资源、状态、环境信息注入到Bean中,使Bean能够感知到这些信息并据此进行相应的操作。
Aware接口主要用来解决以下技术问题:
- 依赖注入:Spring的核心功能之一就是依赖注入(DI),但有时候标准的依赖注入方式可能无法满足某些特定的需求。例如,当需要访问当前Bean的名称、BeanFactory或ApplicationContext等信息,通过实现相应的
Aware接口,可以让Spring容器在初始化Bean时自动将这些信息注入到Bean中。 - 环境感知:有时候,Bean的行为可能需要根据其所处的环境进行调整,例如,在不同的ApplicationContext中,Bean可能需要进行不同的配置或初始化操作,通过实现
ApplicationContextAware接口,Bean可以访问到当前的ApplicationContext,并据此进行环境感知的操作。 - 资源访问:除了基本的依赖注入和环境感知外,
Aware接口还可以用于访问Spring容器中的其他资源。例如,通过实现ResourceLoaderAware接口,Bean可以获得一个ResourceLoader的引用,用于加载类路径下的资源文件。
它有哪些子类拓展?
以下是Aware接口的一些常见的子类实现,如下:
- BeanNameAware: 实现此接口的bean可以获得其在Spring容器中的名称,当bean被创建并添加到容器中时,Spring会调用
setBeanName(String name)方法。 - BeanFactoryAware: 实现此接口的bean可以获得对其所在的
BeanFactory的引用,这允许bean直接访问容器以查找或操作其他bean,通过setBeanFactory(BeanFactory beanFactory)方法注入。 - ApplicationContextAware: 与
BeanFactoryAware类似,但是提供对更高级的ApplicationContext的访问,实现此接口的bean可以通过setApplicationContext(ApplicationContext context)方法获得ApplicationContext的引用。 - MessageSourceAware: 实现此接口的bean可以获得对
MessageSource的引用,这允许bean进行国际化消息的处理,通过setMessageSource(MessageSource messageSource)方法注入。 - ApplicationEventPublisherAware: 实现此接口的bean可以获得一个
ApplicationEventPublisher的引用,用于发布应用事件,Spring会在适当时刻调用setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher)方法。 - ResourceLoaderAware: 实现此接口的bean可以获得对
ResourceLoader的引用,这使得bean可以加载资源,如配置文件等,通过setResourceLoader(ResourceLoader resourceLoader)方法注入。 - EnvironmentAware: 实现此接口的bean可以获得对当前应用环境的
Environment对象的引用。这允许bean查询配置的属性、配置文件等,通过setEnvironment(Environment environment)方法注入。 - EmbeddedValueResolverAware: 实现此接口的bean可以获得对字符串值解析器的引用,该解析器能够处理占位符(如
${...}),通过setEmbeddedValueResolver(StringValueResolver resolver)方法注入。 - SchedulingConfigurerAware (不直接属于
Aware接口系列, 但类似): 允许配置计划任务,在Spring Boot应用中,可以通过实现SchedulingConfigurer接口和覆盖configureTasks(ScheduledTaskRegistrar taskRegistrar)方法来定义计划任务。
代码案例
下面列举举个常见的Aware子类实现案例。
BeanFactoryAware接口
BeanFactoryAware接口允许一个bean在初始化时获得对BeanFactory的引用,这通常用于需要以编程方式访问其他bean或执行与容器相关的操作的场景。下面是一个简单的例子,演示了BeanFactoryAware接口使用,如下代码:
先创建一个实现了BeanFactoryAware接口的类:
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.stereotype.Component; @Component
public class MyBeanFactoryAwareBean implements BeanFactoryAware { private BeanFactory beanFactory; // 实现BeanFactoryAware接口的回调方法 @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; } // 一个简单的方法,用于从BeanFactory中获取bean public Object getBean(String beanName) { return beanFactory.getBean(beanName); }
}
然后,创建一个简单的bean,后面将通过MyBeanFactoryAwareBean来获取它:
import org.springframework.stereotype.Component; @Component
public class MySimpleBean { public String sayHello() { return "Hello from MySimpleBean!"; }
}
接下来,创建一个配置类来启动Spring应用:
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration; @Configuration
@ComponentScan(basePackages = "com.example") // 假设上面的类在com.example包下
public class AppConfig { // 这里不需要额外的bean定义,因为@Component注解已经足够
}
最后,编写一个客户端类来运行应用并测试MyBeanFactoryAwareBean:
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class ClientApp { public static void main(String[] args) { // 创建一个Spring应用上下文 ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); // 获取MyBeanFactoryAwareBean的实例 MyBeanFactoryAwareBean beanFactoryAwareBean = context.getBean(MyBeanFactoryAwareBean.class); // 使用MyBeanFactoryAwareBean来获取MySimpleBean的实例 MySimpleBean simpleBean = (MySimpleBean) beanFactoryAwareBean.getBean("mySimpleBean"); // 调用MySimpleBean的方法并打印结果 System.out.println(simpleBean.sayHello()); // 关闭应用上下文 ((AnnotationConfigApplicationContext) context).close(); }
}
ApplicationContextAware接口
ApplicationContextAware接口允许一个bean在初始化时获得对ApplicationContext的引用,通常用于需要以编程方式访问其他bean或执行与Spring应用上下文相关的操作的场景。
如下代码,演示了如何实现ApplicationContextAware接口,并在客户端代码中调用该bean。
首先,创建一个实现了ApplicationContextAware接口的类:
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component; @Component
public class MyApplicationContextAwareBean implements ApplicationContextAware { private ApplicationContext applicationContext; // 实现ApplicationContextAware接口的回调方法 @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } // 一个简单的方法,用于从ApplicationContext中获取bean public Object getBean(String beanName) { return applicationContext.getBean(beanName); }
}
然后,创建一个简单的bean,稍后将通过MyApplicationContextAwareBean来获取它:
import org.springframework.stereotype.Component; @Component
public class MySimpleBean { public String sayHello() { return "Hello from MySimpleBean!"; }
}
接下来,创建一个配置类来启动Spring应用:
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration; @Configuration
@ComponentScan(basePackages = "com.example") // 假设上面的类在com.example包下
public class AppConfig { // 这里不需要额外的bean定义,因为@Component注解已经足够
}
最后,编写一个客户端类来运行应用并测试MyApplicationContextAwareBean:
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class ClientApp { public static void main(String[] args) { // 创建一个Spring应用上下文 ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); // 获取MyApplicationContextAwareBean的实例 MyApplicationContextAwareBean contextAwareBean = context.getBean(MyApplicationContextAwareBean.class); // 使用MyApplicationContextAwareBean来获取MySimpleBean的实例 MySimpleBean simpleBean = (MySimpleBean) contextAwareBean.getBean("mySimpleBean"); // 调用MySimpleBean的方法并打印结果 System.out.println(simpleBean.sayHello()); // 关闭应用上下文(尽管在这个例子中不是必须的,因为main方法结束后JVM会退出) ((AnnotationConfigApplicationContext) context).close(); }
}
EnvironmentAware接口
EnvironmentAware接口允许bean在其初始化之后访问到Environment属性。
Environment表示当前应用环境,它封装了应用程序环境的配置属性,例如系统属性、环境变量以及应用上下文中的属性。
如下代码,演示了如何实现Environment接口。
创建一个类MyEnvironmentAwareBean实现EnvironmentAware接口:
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.EnvironmentAware;
import org.springframework.context.EnvironmentAwareBean;
import org.springframework.core.env.Environment; public class MyEnvironmentAwareBean implements EnvironmentAware { private Environment environment; // 实现 EnvironmentAware 接口的 setEnvironment 方法 @Override public void setEnvironment(Environment environment) throws BeansException { this.environment = environment; } // 一个简单的方法,用于输出某个属性的值 public void printProperty(String propertyName) { String propertyValue = environment.getProperty(propertyName); System.out.println("Property '" + propertyName + "' = " + propertyValue); }
}
上面的代码中MyEnvironmentAwareBean类实现了EnvironmentAware接口,并通过setEnvironment方法接收Environment对象。
接下来,配置Spring上下文,注册MyEnvironmentAwareBean bean,并通过一个客户端类调用它:
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; @Configuration
public class AppConfig { // 声明 MyEnvironmentAwareBean 为一个 bean @Bean public MyEnvironmentAwareBean myEnvironmentAwareBean() { return new MyEnvironmentAwareBean(); }
} public class ClientApp { public static void main(String[] args) { // 创建 AnnotationConfigApplicationContext 上下文 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); // 从上下文中获取 MyEnvironmentAwareBean 实例 MyEnvironmentAwareBean myBean = context.getBean(MyEnvironmentAwareBean.class); // 调用 printProperty 方法,打印系统属性 java.version myBean.printProperty("java.version"); // 关闭上下文 context.close(); }
}
ResourceLoaderAware接口
如下代码,演示了如何实现Environment接口:
创建一个类MyResourceLoaderAwareComponent实现ResourceLoaderAware接口,并实现setResourceLoader方法
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Component; import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.Scanner; // 声明这是一个Spring组件
@Component
public class MyResourceLoaderAwareComponent implements ResourceLoaderAware { private ResourceLoader resourceLoader; // 实现了ResourceLoaderAware接口的setResourceLoader方法 @Override public void setResourceLoader(ResourceLoader resourceLoader) { this.resourceLoader = resourceLoader; } // 使用ResourceLoader加载资源并返回资源内容 public String loadResourceContent(String location) { Resource resource = resourceLoader.getResource(location); try (InputStream inputStream = resource.getInputStream(); Scanner scanner = new Scanner(inputStream, StandardCharsets.UTF_8.name())) { StringBuilder content = new StringBuilder(); while (scanner.hasNextLine()) { content.append(scanner.nextLine()).append("\n"); } return content.toString(); } catch (IOException e) { throw new RuntimeException("Failed to load resource: " + location, e); } }
}
创建换一个client类MyResourceLoaderAwareClient,类中通过@Autowired将MyResourceLoaderAwareComponent注入进来,如下:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; @Component
public class MyResourceLoaderAwareClient { private final MyResourceLoaderAwareComponent myResourceLoaderAwareComponent; @Autowired public MyResourceLoaderAwareClient(MyResourceLoaderAwareComponent myResourceLoaderAwareComponent) { this.myResourceLoaderAwareComponent = myResourceLoaderAwareComponent; } // 客户端方法,用于调用加载资源的方法并打印结果 public void printResourceContent(String location) { String content = myResourceLoaderAwareComponent.loadResourceContent(location); System.out.println("Resource content from location: " + location); System.out.println(content); }
}

最后,Aware子类比较多,这里就不一一通过代码举例了,但是只需要记住,在Spring中提供的Aware接口都是为了能够让开发者轻松地获取到Spring容器中的其他资源的引用。

END!
END!
END!
往期回顾
精品文章
Spring揭秘:@import注解应用场景及实现原理!
Java并发基础:原子类之AtomicMarkableReference全面解析!
Java并发基础:concurrent Flow API全面解析
Java并发基础:CopyOnWriteArraySet全面解析
Java并发基础:ConcurrentSkipListMap全面解析
相关文章:
Spring揭秘:Aware接口应用场景及实现原理!
内容概要 Aware接口赋予了Bean更多自感知的能力,通过实现不同的Aware接口,Bean可以轻松地获取到Spring容器中的其他资源引用,像ApplicationContext、BeanFactory等。 这样不仅增强了Bean的功能,还提高了代码的可维护性和扩展性&…...
校园小情书微信小程序,社区小程序前后端开源,校园表白墙交友小程序
功能 表白墙卖舍友步数旅行步数排行榜情侣脸漫画脸个人主页私信站内消息今日话题评论点赞收藏 效果图...
从Pandas到Polars :数据的ETL和查询
对于我们日常的数据清理、预处理和分析方面的大多数任务,Pandas已经绰绰有余。但是当数据量变得非常大时,它的性能开始下降。 本文将介绍如何将日常的数据ETL和查询过滤的Pandas转换成polars。 图片 Polars的优势 Polars是一个用于Rust和Python的Data…...
Node.Js编码注意事项
Node.js 中不能使用 BOM 和 DOM 的 API,可以使用 console 和定时器 APINode.js 中的顶级对象为 global,也可以用 globalThis 访问顶级对象 浏览器端js的组成 Node.js中的JavaScript组成 相比较之下发现只有console与定时器是两个API所共有的ÿ…...
floodfill算法题目
前言 大家好,我是jiantaoyab,在下面的题目中慢慢体会floodFill算法,虽然是新的算法,但是用的思想和前面的文章几乎一样,代码格式也几乎一样,但不要去背代码 图像渲染 https://leetcode.cn/problems/flood…...
AI相关的实用工具分享
AI实用工具大赏:赋能科研与生活,探索AI的无限可能 前言 在数字化浪潮汹涌而至的今天,人工智能(AI)已经渗透到我们生活的方方面面,无论是工作还是生活,都在悄然发生改变。AI的崛起不仅为我们带…...
K8s — PVC|PV Terminating State
在本文中,我们将讨论PV和PVC一直Terminating的状态。 何时会Terminting? 在以下情况下,资源将处于Terminating状态。 在删除Bounded 状态的PVC之前,删除了对应的PV,PV在删除后是Terminting状态。删除PVC时,仍有引用…...
C语言 --- 指针(5)
目录 一.sizeof和strlen对比 1.sizeof 2.strlen 3.strlen 和sizeof的对比 二.数组和指针笔试题目详解 回顾:数组名的理解 1.一维数组 2.字符数组 代码1: 代码2: 代码3: 代码4: 代码5: 代码6&am…...
Android Studio Iguana | 2023.2.1版本
Android Gradle 插件和 Android Studio 兼容性 Android Studio 构建系统基于 Gradle,并且 Android Gradle 插件 (AGP) 添加了一些特定于构建 Android 应用程序的功能。下表列出了每个版本的 Android Studio 所需的 AGP 版本。 如果特定版本的 Android Studio 不支持…...
并查集(蓝桥杯 C++ 题目 代码 注解)
目录 介绍: 模板: 题目一(合根植物): 代码: 题目二(蓝桥幼儿园): 代码: 题目三(小猪存钱罐): 代码: …...
MapReduce内存参数自动推断
MapReduce内存参数自动推断。在Hadoop 2.0中,为MapReduce作业设置内存参数非常繁琐,涉及到两个参数:mapreduce.{map,reduce}.memory.mb和mapreduce.{map,reduce}.java.opts,一旦设置不合理,则会使得内存资源浪费严重&a…...
pyside6 pytq PyDracula QVideoWidget视频只有画面没有声音
解决方案: 先不使用框架,纯pyside6代码,如果添加视频有画面有声音,那可以排除是硬件问题,如果没有画面只有声音,可能是视频解码器无法解码,换个格式的视频文件如果只有使用PyDracula 出问题&am…...
Axure基础 各元件的作用及介绍
图像热区 增加按钮或者文本的点击区域,他是透明的,在预览时看不见。 动态面板 用来绘制一下带交互效果的元件,他是动态的,如轮播图,一个动态面板里可以有多个子面板,每一个子面板对应着不同的效果。 他…...
学习Java的第六天
目录 一、变量 1、变量的定义 2、变量的声明格式 3、变量的注意事项 4、变量的作用域 二、常量 三、命名规范 Java 语言支持如下运算符: 1、算术运算符 解析图: 示例: 2、赋值运算符 解析图: 示例: 3、关…...
基于Spring Boot+ Vue的房屋租赁系统
末尾获取源码作者介绍:大家好,我是墨韵,本人4年开发经验,专注定制项目开发 更多项目:CSDN主页YAML墨韵 学如逆水行舟,不进则退。学习如赶路,不能慢一步。 目录 一、项目简介 二、开发技术与环…...
多轨迹建模方法的介绍与实操-基于R语言
本文介绍了多轨迹建模方法(Group-Based Multivariate Trajectory Modeling),这是一种扩展了单指标组基轨迹建模的技术,用于分析多个疾病生物标志物或临床重要因素的联合轨迹,以更好地理解和追踪疾病进程、行为或健康状…...
【Spring】Spring状态机
1.什么是状态机 (1). 什么是状态 先来解释什么是“状态”( State )。现实事物是有不同状态的,例如一个自动门,就有 open 和 closed 两种状态。我们通常所说的状态机是有限状态机,也就是被描述的事物的状态的数量是有…...
Node.js基础---使用Express写接口
1. 创建基本的服务器 2. 创建 API 路由模块 // aoiRouter.js 路由模块 const express require(express) const apiRouter express.Router()module.exports apiRouter// ------------------------------------------// app.js 导入并注册路由模块 const apiRouter require(…...
小蓝的钥匙(蓝桥杯错排)
现在有28个小朋友,每个人手上有一把钥匙,每一个钥匙都只能打开自己的房间门,现在将所有钥匙都收上来,然后再随机打乱分给每个小朋友,也就是有28!的分法,请问现在其中14个小朋友的钥匙能恰好打开…...
【Python】科研代码学习:八 FineTune PretrainedModel (用 trainer,用 script);LLM文本生成
【Python】科研代码学习:八 FineTune PretrainedModel [用 trainer,用 script] LLM文本生成 自己整理的 HF 库的核心关系图用 trainer 来微调一个预训练模型用 script 来做训练任务使用 LLM 做生成任务可能犯的错误,以及解决措施 自己整理的 …...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...
【AI学习】三、AI算法中的向量
在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...
Java入门学习详细版(一)
大家好,Java 学习是一个系统学习的过程,核心原则就是“理论 实践 坚持”,并且需循序渐进,不可过于着急,本篇文章推出的这份详细入门学习资料将带大家从零基础开始,逐步掌握 Java 的核心概念和编程技能。 …...
深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...
Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...
Element Plus 表单(el-form)中关于正整数输入的校验规则
目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入(联动)2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...
学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”
2025年#高考 将在近日拉开帷幕,#AI 监考一度冲上热搜。当AI深度融入高考,#时间同步 不再是辅助功能,而是决定AI监考系统成败的“生命线”。 AI亮相2025高考,40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕,江西、…...
中医有效性探讨
文章目录 西医是如何发展到以生物化学为药理基础的现代医学?传统医学奠基期(远古 - 17 世纪)近代医学转型期(17 世纪 - 19 世纪末)现代医学成熟期(20世纪至今) 中医的源远流长和一脉相承远古至…...
人机融合智能 | “人智交互”跨学科新领域
本文系统地提出基于“以人为中心AI(HCAI)”理念的人-人工智能交互(人智交互)这一跨学科新领域及框架,定义人智交互领域的理念、基本理论和关键问题、方法、开发流程和参与团队等,阐述提出人智交互新领域的意义。然后,提出人智交互研究的三种新范式取向以及它们的意义。最后,总结…...
招商蛇口 | 执笔CID,启幕低密生活新境
作为中国城市生长的力量,招商蛇口以“美好生活承载者”为使命,深耕全球111座城市,以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子,招商蛇口始终与城市发展同频共振,以建筑诠释对土地与生活的…...
