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依赖注入管理的更多相关文章

  1. ASP.NET Core中的依赖注入(4): 构造函数的选择与服务生命周期管理

    ServiceProvider最终提供的服务实例都是根据对应的ServiceDescriptor创建的,对于一个具体的ServiceDescriptor对象来说,如果它的ImplementationI ...

  2. 依赖注入及AOP简述(十一)——生命周期管理 .

    2.     生命周期管理 各种依赖注入框架提供了替开发者管理各种Scope的便利功能,随之而来的就必然是被管理的依赖对象的生命周期管理的问题.所谓生命周期管理,就是一个对象在它所属的Scope中从被 ...

  3. 05、NetCore2.0依赖注入(DI)之Web应用启动流程管理

    05.NetCore2.0依赖注入(DI)之Web应用启动流程管理 在一个Asp.net core 2.0 Web应用程序中,启动过程都做了些什么?NetCore2.0的依赖注入(DI)框架是如何管理 ...

  4. DI容器Ninject在管理接口和实现、基类和派生类并实现依赖注入方面的实例

    当一个类依赖于另一个具体类的时候,这样很容易形成两者间的"强耦合"关系.我们通常根据具体类抽象出一个接口,然后让类来依赖这个接口,这样就形成了"松耦合"关系,有 ...

  5. Ioc 器管理的应用程序设计,前奏:容器属于哪里? 控制容器的反转和依赖注入模式

    Ioc 器管理的应用程序设计,前奏:容器属于哪里?   我将讨论一些我认为应该应用于“容器管理”应用程序设计的原则. 模式1:服务字典 字典或关联数组是我们在软件工程中学到的第一个构造. 很容易看到使 ...

  6. Spring的依赖注入和管理Bean

    采用Spring管理Bean和依赖注入 1.实例化spring容器 和 从容器获取Bean对象 实例化Spring容器常用的两种方式: 方法一: 在类路径下寻找配置文件来实例化容器 [推荐使用] Ap ...

  7. ASP.NET Core中的依赖注入: 构造函数的选择与服务生命周期管理

    ServiceProvider最终提供的服务实例都是根据对应的ServiceDescriptor创建的,对于一个具体的ServiceDescriptor对象来说,如果它的ImplementationI ...

  8. ASP。使用依赖注入的asp.net Core 2.0用户角色库动态菜单管理

    下载source code - 2.2 MB 介绍 在开始这篇文章之前,请阅读我的前一篇文章: 开始使用ASP.NET Core 2.0身份和角色管理 在上一篇文章中,我们详细讨论了如何使用ASP.N ...

  9. Blazor和Vue对比学习(进阶2.2.3):状态管理之状态共享,Blazor的依赖注入和第三方库Fluxor

    Blazor没有提供状态共享的方案,虽然依赖注入可以实现一个全局对象,这个对象可以拥有状态.计算属性.方法等特征,但并不具备响应式.比如,组件A和组件B,都注入了这个全局对象,并引用了全局对象上的数据 ...

  10. Spring Framework------>version4.3.5.RELAESE----->Reference Documentation学习心得----->使用spring framework的IoC容器功能----->方法一:使用XML文件定义beans之间的依赖注入关系

    XML-based configuration metadata(使用XML文件定义beans之间的依赖注入关系) 第一部分 编程思路概述 step1,在XML文件中定义各个bean之间的依赖关系. ...

随机推荐

  1. Node.js 20 —— 几个令人大开眼界的特性

    前言:欢迎来到 Node.js 20 Node.js 20 已经发布,带来了创新和激动人心的新时代.这个开创性的版本于2023年4月18日首次亮相,并将在2023年10月发布长期支持(LTS)版本,并 ...

  2. Jellyfin Documentation

    Skip to main content     Introduction On this page Welcome to the Jellyfin Documentation Jellyfin is ...

  3. MySQL PXC 集群运维指南

    目录 一.PXC方案概述 二.PXC基础知识 三.PXC节点的配置安装 四.PXC节点的上线与下线 五.其他 一.PXC方案概述 Percona XtraDB Cluster (PXC) 是一个完全开 ...

  4. Unity EditorWindow GUI裁剪

    Unity2017,想在编辑器自己实现一个类似TreeView的东西 public void OnGUI(Rect rect) { // ... for (int i = 0; i < 100; ...

  5. 实战攻防演练-利用Everything搜索软件进行内网后渗透利用

    前言 Everything是一款很出名的文件搜索工具,基于文件.文件夹名称的快速搜索的轻量级的软件,而早在几年前就有很多apt组织利用everything来进行文件查找等,前几年在T00ls上也有人发 ...

  6. [C++]P3384 轻重链剖分(树链剖分)

    [C++]树链剖分 预备知识 树的基础知识 关于这个本文有介绍 邻接表存图 线段树基础 会区间加法和区间结合就可以了P3372 建议阅读这篇Blog 最近公共祖先LCA 虽然用不到这个思想 但是有类似 ...

  7. MongoDB-SQL语法

    MongoDB-SQL语法 可视化软件:Navicat 1. MongoDB-查询 db.getCollection('表名').find({}); db.getCollection('表名').fi ...

  8. 一、Linux发展史

    一.Linux发展史及红帽认证 红帽授权培训合作伙伴 木兰宽松许可证 1. Linux系统发展史 1. Unix发展历程 上世纪六十年代贝尔实验室(Bell).麻省理工学院(MIT)以及通用电气(GE ...

  9. C语言一个单链表L=(a1 , a2 , … , an-1 , an),其逆单链表定义为L’=( an , an-1 , … , a2 , a1),要求逆单链表仍占用原单链表的空间。

    /* 开发者:慢蜗牛 开发时间:2020.6.11 程序功能:顺序输出和逆序输出 */ #include<stdio.h> #include<malloc.h> #define ...

  10. LabVIEW基于机器视觉的实验室设备管理系统(5)

    目录 行动计划 设备借用 判断设备ID是否正确.设备是否在库 判断是否为已注册用户.电话是否正确 借出设备 设备归还 信息查询 ​判断ID是否正确.选择设备状态 效果演示 今天这一期,我们就来完成实验 ...