Aware依赖注入管理
1.Aware介绍
在Spring当中有一些内置的对象是未开放给我们使用的,例如Spring的上下文ApplicationContext、环境属性Environment,BeanFactory等等其他的一些内置对象,而在我们可以通过实现对应的Aware接口去拿到我们想要的一些属性,一般命名都是xxxAware,在创建对象的时候, 会调用接口规定的方法注入到相关组件:Aware。
Bean生命周期内常见的:BeanNameAware、ApplicationContextAware、BeanFactoryAware 。
- BeanNameAware 接口只有一个方法 setBeanName()。实现 BeanNameAware 接口的 bean,在 bean 加载的过程中可以获取到该 bean 的 id。
- ApplicationContextAware 接口只有一个方法 setApplicationContext()。实现 ApplicationContextAware 接口的 bean,可以在 bean 加载的过程中可以获取到 Spring 的 ApplicationContext,从而能够获取任意 bean 及大量 IOC 容器信息
- BeanFactoryAware 接口只有一个方法 setBeanFactory()。实现 BeanFactoryAware 接口的 bean,可以在 bean 加载的过程中可以获取到加载该 bean 的 BeanFactory
public class TestBean implements BeanNameAware, ApplicationContextAware, BeanFactoryAware{
//获取当前bean的name
@Override
public void setBeanName(String name) {
System.out.println("setBeanName()...beanName=" + name);
}
//获取当前ApplicationContext
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("setApplicationContext()...applicationContext=" + applicationContext);
}
//获取当前BeanFactory
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("setBeanFactory()...beanFactory=" + beanFactory);
}
}
测试类:
@SpringBootApplication
@EnableAspectJAutoProxy
public class DemoApplication{
public static void main(String[] args) {
// 创建一个AnnotationConfigApplicationContext容器
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
// 注册TestBean02到容器中
context.register(TestBean02.class);
// 刷新容器,启动应用上下文
context.refresh();
// 关闭容器,销毁应用上下文
context.close();
}
}
结果:

总结:这些接口提供了一种在Bean中与Spring容器交互的机制,但需要注意的是,过度使用 Aware 接口可能导致代码与Spring框架的紧耦合。在实际应用中,更推荐使用依赖注入的方式来获取所需的资源,以保持代码的灵活性和清晰性。 Aware 接口通常在一些特定场景下使用,例如需要在Bean初始化时获取容器信息的情况。
2.通过自定义Aware来实现数据源的自动注入
目标:完成不使用比如@Autowired和@Resource来实现自动注入 主要实现是通过自定义Aware接口搭配BeanPostProcessor接口实现功能。
- 1.创建数据源对象DataBaseConfig:
public class DataBaseConfig {
//数据库url
private String url;
//数据库名称
private String name;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "DataBaseConfig{" + "url='" + url + '\'' + ", name='" + name + '\'' + '}';
}
}
- 2.创建自定义Aware接口:DataBaseAware负责自动注入DataBase对象
public interface DataBaseAware extends Aware { //仅标记
//自动注入DataBase对象
void setDataBase(DataBaseConfig dataBaseConfig);
}
- 3.核心内容就是通过自定义BeanPostProcessor来实现对DataBase对象的自动注入:DataBaseConfigBeanPostProcessor
public class DataBaseConfigBeanPostProcessor implements BeanPostProcessor, ApplicationContextAware {
//实现ApplicationContextAware只为获取Bean
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
//获取当前容器
this.applicationContext=applicationContext;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
//获取database对象
Object config = applicationContext.getBean("dataBaseConfig");
if (bean==null){ //已经注入bean了
return bean; //直接返回
}
if (config instanceof DataBaseConfig &&bean instanceof DataBaseAware){
((DataBaseAware) bean).setDataBase((DataBaseConfig) config);
}
return bean;
}
}
- 4.通过实现
DataBaseAware接口并实现相关方法,来接收并访问DataBaseConfig对象的依赖:MyDataBase
public class MyDataBase implements DataBaseAware{ //定义接口实现子类
private DataBaseConfig config;
@Override
public void setDataBase(DataBaseConfig dataBaseConfig) {
this.config=dataBaseConfig;
}
public DataBaseConfig getConfig() {
return config;
}
}
- 5.测试配置类:对所有bean进行注册,AwareDataBaseConfig
@Configuration
public class AwareDataBaseConfig {
@Bean
public DataBaseConfig dataBaseConfig(){
DataBaseConfig dataBaseConfig = new DataBaseConfig();
dataBaseConfig.setName("测试数据库");
dataBaseConfig.setUrl("jdbc:mysql://localhost:3306/test");
return dataBaseConfig;
}
@Bean
public DataBaseConfigBeanPostProcessor dataBaseConfigBeanPostProcessor(){
return new DataBaseConfigBeanPostProcessor();
}
@Bean
public MyDataBase myDataBase(){
return new MyDataBase();
}
}
- 6.启动类测试效果:
@SpringBootApplication
@ComponentScan("com.example.demo.aware")
public class DemoApplication{
public static void main(String[] args) {
// 创建一个AnnotationConfigApplicationContext容器
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AwareDataBaseConfig.class);
MyDataBase bean = context.getBean(MyDataBase.class);
System.out.println(bean.getConfig().getClass());
// 关闭容器,销毁应用上下文
context.close();
}
}
最终效果图:

总结:
为什么不使用@Autowired` 和 `@Resource` 来用于实现自动依赖注入。这两者通常用于将其他组件或配置信息注入到一个类中,而不需要手动编写大量的依赖注入代码。相比之下,`Aware` 接口是一种更为灵活和手动的依赖注入方式 但代码量要大的多 如果对于已经提供了BeanPostProcessor实现类是一种方便的做法。
- 更灵活的自定义逻辑:** 使用 `Aware` 接口,你可以在对象初始化的不同阶段执行自定义的逻辑。这对于需要更复杂的依赖注入场景或特定的初始化逻辑非常有用。
- 特定场景的定制化:** 有时候,你可能需要在对象创建或初始化的过程中执行一些特定的逻辑,而不仅仅是简单的属性注入。`Aware` 接口允许你在需要的时候执行这些逻辑。
- 不依赖于注解:** 某些项目或团队可能更喜欢避免使用过多的注解,而更倾向于在代码中显式地表达依赖关系。这种情况下,使用 `Aware` 接口可以更符合团队的编码风格。
- 更细粒度的控制:** `Aware` 接口提供了更细粒度的控制,允许你手动管理依赖注入的过程。这对于一些复杂的业务逻辑可能更容易实现。
总的来说,选择使用 `Aware` 接口还是注解方式取决于项目的需求和开发团队的偏好。注解方式通常更简洁和方便,而 `Aware` 接口提供了更多的自定义和控制的能力。在实际项目中,根据具体情况选择最适合的方式是很重要的。
Aware依赖注入管理的更多相关文章
- ASP.NET Core中的依赖注入(4): 构造函数的选择与服务生命周期管理
ServiceProvider最终提供的服务实例都是根据对应的ServiceDescriptor创建的,对于一个具体的ServiceDescriptor对象来说,如果它的ImplementationI ...
- 依赖注入及AOP简述(十一)——生命周期管理 .
2. 生命周期管理 各种依赖注入框架提供了替开发者管理各种Scope的便利功能,随之而来的就必然是被管理的依赖对象的生命周期管理的问题.所谓生命周期管理,就是一个对象在它所属的Scope中从被 ...
- 05、NetCore2.0依赖注入(DI)之Web应用启动流程管理
05.NetCore2.0依赖注入(DI)之Web应用启动流程管理 在一个Asp.net core 2.0 Web应用程序中,启动过程都做了些什么?NetCore2.0的依赖注入(DI)框架是如何管理 ...
- DI容器Ninject在管理接口和实现、基类和派生类并实现依赖注入方面的实例
当一个类依赖于另一个具体类的时候,这样很容易形成两者间的"强耦合"关系.我们通常根据具体类抽象出一个接口,然后让类来依赖这个接口,这样就形成了"松耦合"关系,有 ...
- Ioc 器管理的应用程序设计,前奏:容器属于哪里? 控制容器的反转和依赖注入模式
Ioc 器管理的应用程序设计,前奏:容器属于哪里? 我将讨论一些我认为应该应用于“容器管理”应用程序设计的原则. 模式1:服务字典 字典或关联数组是我们在软件工程中学到的第一个构造. 很容易看到使 ...
- Spring的依赖注入和管理Bean
采用Spring管理Bean和依赖注入 1.实例化spring容器 和 从容器获取Bean对象 实例化Spring容器常用的两种方式: 方法一: 在类路径下寻找配置文件来实例化容器 [推荐使用] Ap ...
- ASP.NET Core中的依赖注入: 构造函数的选择与服务生命周期管理
ServiceProvider最终提供的服务实例都是根据对应的ServiceDescriptor创建的,对于一个具体的ServiceDescriptor对象来说,如果它的ImplementationI ...
- ASP。使用依赖注入的asp.net Core 2.0用户角色库动态菜单管理
下载source code - 2.2 MB 介绍 在开始这篇文章之前,请阅读我的前一篇文章: 开始使用ASP.NET Core 2.0身份和角色管理 在上一篇文章中,我们详细讨论了如何使用ASP.N ...
- Blazor和Vue对比学习(进阶2.2.3):状态管理之状态共享,Blazor的依赖注入和第三方库Fluxor
Blazor没有提供状态共享的方案,虽然依赖注入可以实现一个全局对象,这个对象可以拥有状态.计算属性.方法等特征,但并不具备响应式.比如,组件A和组件B,都注入了这个全局对象,并引用了全局对象上的数据 ...
- Spring Framework------>version4.3.5.RELAESE----->Reference Documentation学习心得----->使用spring framework的IoC容器功能----->方法一:使用XML文件定义beans之间的依赖注入关系
XML-based configuration metadata(使用XML文件定义beans之间的依赖注入关系) 第一部分 编程思路概述 step1,在XML文件中定义各个bean之间的依赖关系. ...
随机推荐
- firewalld规则配置
firewalld规则配置 一.概念 动态防火墙 启动新规则时,不会像iptables一样,先清空规则,再启动所有规则,如此会对现在程序有影响,哪怕只是一条规则.而firewalld 规则变更不需要对 ...
- PostgreSQL学习笔记-6.基础知识:ALTER、TRUNCATE 、View(视图)、TRANSACTION 事务、LOCK 锁
ALTER TABLE 命令 在 PostgreSQL 中,ALTER TABLE 命令用于添加,修改,删除一张已经存在表的列. 另外你也可以用 ALTER TABLE 命令添加和删除约束. 语法 用 ...
- 铅华洗尽,粉黛不施,人工智能AI基于ProPainter技术去除图片以及视频水印(Python3.10)
视频以及图片修复技术是一项具有挑战性的AI视觉任务,它涉及在视频或者图片序列中填补缺失或损坏的区域,同时保持空间和时间的连贯性.该技术在视频补全.对象移除.视频恢复等领域有广泛应用.近年来,两种突出的 ...
- 可视化-vscode安装matplotlib工具
可视化工具中,最流行的工具之一是 Matplotlib,它是一个数学绘图库,可以制作简单的图表,如折线图和散点图: 使用pip可以安装Matplotlib: 安装步骤:: 1.在vscode的终端输入 ...
- vue本地能够访问图片,打包项目之后图片无法访问
//template中 <img :src="boxHerf" /> //js let boxHerf = ref('/src/assets/images/contai ...
- 中兴GoldenDB(MYSQL)营运商SQL优化案例(超复杂SQL)
陆老师好久没找我,今天他在营运商遇到2条性能慢的SQL,说找了好多专家老手看了都优化不了,然后就找到我打算给我玩玩. 第一次接触营运商行业的SQL,妈呦还真的复杂 SQL1: SELECT WORK ...
- GitHub 术语解释
为了大家进一步了解和使用 GitHub,在本文中,我们一起来看看 GitHub 的常用术语,也可以说是基本概念: Repository:简称Repo,可以理解为"仓库",我们的项目 ...
- testre
f5看到关键代码判断 猜测这是flag或者是加密后的结果,直接将其当作flag答案不对,所以猜测为加密后的结果,然后再通过其他函数了解 跟进第一个函数发现编码表 本来想试试base解密,可是当时只试了 ...
- FPGA常用IP核
前言: 芯片行业中的IP,一般称为IP(Intellectual Property)核,是具有知识产权核的集成电路芯核的总称.说白了就是厂家实现的具有特定功能工具,然后我们可以直接调用,就相当于是函数 ...
- Verilog HDL门级建模
Verilog HDL内部定义了12个基本门级元件可以直接用,用这些门级原件直接对逻辑图进行描述,称为门级建模. 每个门输入可能是逻辑0,逻辑1,不确定态x和高阻态z四个值之一. 1.多输入门 主要有 ...