Spring揭秘:ApplicationContextAware应用场景及实现原理!

news2024/10/23 0:22:02

Spring揭秘:ImportBeanDefinitionRegistrar应用场景及实现原理! - 程序员古德

内容概要

ApplicationContextAware接口能够轻松感知并在Spring中获取应用上下文,进而访问容器中的其他Bean和资源,这增强了组件间的解耦,了代码的灵活性和可扩展性,是Spring框架中实现高级功能的关键接口之一。

核心概念

它能用来干啥?

为了方便理解,模拟一个业务场景。假如有一个功能模块负责处理订单,在这个模块中,有一个OrderService类,它负责订单的创建、更新和查询等操作,单在处理订单的过程中,可能需要访问其他一些服务,比如用户服务来获取用户信息,或者库存服务来检查商品库存。

在这个场景中,可以使用ApplicationContextAware接口来解决,可以创建一个类,比如叫OrderServiceContextAware,让它实现ApplicationContextAware接口,当Spring容器初始化这个类时,它会自动将应用上下文注入到这个类中,一旦注入了应用上下文,OrderServiceContextAware就能够访问到容器中的其他Bean,包括用户服务和库存服务。

可以在OrderService类中使用OrderServiceContextAware来获取用户服务和库存服务的实例,而无需直接在OrderService中注入这些服务,这样OrderService类不直接依赖于其他服务的具体实现,而是通过OrderServiceContextAware来间接访问这些服务。

它有哪些特性?

ApplicationContextAware是Spring框架提供的一个特殊的回调接口,用于帮助对象(特别是普通的Java Bean)访问到Spring的应用上下文ApplicationContext

当在自己的类中实现ApplicationContextAware接口时,可以通过Spring提供的回调机制访问到Spring的应用上下文,从而获得Spring IoC容器中的bean实例、配置信息以及进行国际化操作、事件发布等操作。

ApplicationContextAware接口中定义了一个setApplicationContext方法,当类实现了该接口之后,Spring IoC容器会自动调用该方法并将当前的ApplicationContext注入到所实现的setApplicationContext方法中,这样就可以在该类中使用Spring的应用上下文了。

在一些开源的Spring工具库中会看到这种技术的使用,因为这些库往往需要与Spring容器交互,比如读取容器的配置,访问其他的bean等等,通过实现ApplicationContextAware接口就可以非常方便地完成这些工作。

但注意,一般不推荐在的业务代码中使用,因为这样会增加代码与Spring的耦合性,违反了“依赖于抽象,而非依赖于具体实现”的面向对象设计原则。业务代码应当尽可能减少对具体框架的依赖,以提高代码的通用性和可移植性。

代码案例

下面是一个简单的代码案例,展示了如何使用ApplicationContextAware接口来创建一个能够访问Spring应用上下文的类,如下代码:

首先,创建一个实现ApplicationContextAware接口的类:

import org.springframework.beans.BeansException;  
import org.springframework.context.ApplicationContext;  
import org.springframework.context.ApplicationContextAware;  
import org.springframework.stereotype.Component;  
  
@Component  
public class SpringContextUtil implements ApplicationContextAware {  
  
    // Spring应用上下文  
    private static ApplicationContext applicationContext;  
  
    // 当Spring容器创建该类的实例时,会自动调用此方法,注入应用上下文  
    @Override  
    public void setApplicationContext(ApplicationContext context) throws BeansException {  
        SpringContextUtil.applicationContext = context;  
    }  
  
    // 提供一个静态方法,返回应用上下文  
    public static ApplicationContext getApplicationContext() {  
        return applicationContext;  
    }  
  
    // 提供一个获取Bean的静态方法  
    public static <T> T getBean(Class<T> beanClass) {  
        if (applicationContext != null) {  
            return applicationContext.getBean(beanClass);  
        } else {  
            throw new IllegalStateException("ApplicationContext is not initialized yet!");  
        }  
    }  
}

接着,定义一个简单的服务类作为Spring Bean:

import org.springframework.stereotype.Service;  
  
@Service  
public class DemoService {  
      
    public String sayHello() {  
        return "Hello from DemoService!";  
    }  
}

然后,可以使用Spring的Java配置或者XML配置来定义和初始化这些Bean,假设使用Java配置:

import org.springframework.context.annotation.Bean;  
import org.springframework.context.annotation.Configuration;  
  
@Configuration  
public class AppConfig {  
  
    @Bean  
    public SpringContextUtil springContextUtil() {  
        return new SpringContextUtil();  
    }  
  
    @Bean  
    public DemoService demoService() {  
        return new DemoService();  
    }  
}

最后,在客户端代码中,我们可以通过SpringContextUtil类来获取DemoService的实例并调用其方法:

import org.springframework.context.annotation.AnnotationConfigApplicationContext;  
  
public class ApplicationClient {  
  
    public static void main(String[] args) {  
        // 创建Spring上下文,注册Java配置类  
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);  
          
        // 关闭Spring上下文,以便能够正常结束程序(尽管在这个示例中可能不需要)  
        context.registerShutdownHook();  
          
        // 通过SpringContextUtil获取DemoService实例  
        DemoService demoService = SpringContextUtil.getBean(DemoService.class);  
          
        // 调用DemoService的sayHello方法  
        System.out.println(demoService.sayHello());  
    }  
}

输出结果:

复制代码

Hello from DemoService!

以上代码展示了如何通过SpringContextUtil访问Spring的应用上下文,并获取其中的一个bean(DemoService)。

ApplicationClient类是客户端代码的入口点,它初始化了一个AnnotationConfigApplicationContext,通过它Spring可以创建和管理beans,随后客户端代码使用SpringContextUtil.getBean静态方法来获取DemoService的实例,并调用它的sayHello方法。

核心API

ApplicationContextAware接口是一个特殊的标记接口。

它允许实现类能够访问到ApplicationContext,即Spring的应用上下文,ApplicationContextAware中有且只有一个核心方法,如下是该方法的说明:

public interface ApplicationContextAware extends Aware {  
    void setApplicationContext(ApplicationContext applicationContext) throws BeansException;  
}

setApplicationContext方法的含义如下:

  • void setApplicationContext(ApplicationContext applicationContext) throws BeansException:
    这个方法会在Spring容器初始化的时候被自动调用,Spring容器会将当前的ApplicationContext作为参数传递给该方法,实现这个接口的类可以在这个方法中保存对ApplicationContext的引用,从而能够在后续的操作中使用这个上下文。

如下是实现ApplicationContextAware接口的类的代码案例,如下:

@Component  
public class MyApplicationContextAware implements ApplicationContextAware {  
    private ApplicationContext applicationContext;  
  
    @Override  
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {  
        this.applicationContext = applicationContext;  
    }  
  
    public ApplicationContext getApplicationContext() {  
        return this.applicationContext;  
    }  
}

技术原理

ApplicationContextAware接口是Spring框架中用于让Bean感知到Spring应用上下文ApplicationContext的存在的一个标记接口。

当Spring容器创建一个实现了ApplicationContextAware接口的Bean时,它会自动调用该Bean的setApplicationContext方法,并将当前的ApplicationContext作为参数传入,这使得Bean能够访问到Spring容器的上下文,进而可以获取容器中的其他Bean、资源、配置信息等。

实现原理

  1. 标记接口: ApplicationContextAware接口本身并没有定义任何具体的业务逻辑,它只是一个标记接口,用于告诉Spring容器这个Bean需要特殊处理。
  2. 容器回调: 当Spring容器初始化一个Bean时,如果这个Bean实现了ApplicationContextAware接口,Spring容器会调用该Bean的setApplicationContext方法,并将当前的ApplicationContext对象作为参数传入。
  3. 内部状态保存: 实现ApplicationContextAware接口的Bean通常会在其内部保存这个传入的ApplicationContext引用,以便后续使用。
  4. 使用上下文: 一旦Bean保存了ApplicationContext的引用,它就可以使用这个上下文来访问容器中的其他Bean,或者获取容器的其他服务。

工作机制

  1. Bean创建: 当Spring容器根据配置信息创建一个Bean实例时,它会检查这个Bean是否实现了任何Aware接口(包括ApplicationContextAware)。
  2. Aware接口处理: 如果Bean实现了Aware接口,Spring容器会调用相应的set*方法,注入相应的依赖,对于ApplicationContextAware,容器会调用setApplicationContext方法。
  3. 依赖注入: 在调用setApplicationContext方法时,Spring容器会将当前的ApplicationContext对象注入到Bean中,这个注入过程是通过Java反射机制实现的。
  4. Bean后处理: 在Bean的所有属性被设置之后,Spring容器会调用Bean的后处理器(如果配置了的话),进行额外的初始化工作,对于实现了InitializingBean接口的Bean,还会调用其afterPropertiesSet方法。
  5. 使用ApplicationContext: 一旦Bean被初始化并注入了ApplicationContext,它就可以使用这个上下文来执行各种操作,比如获取其他Bean、访问资源、读取配置等。

核心总结

Spring揭秘:ApplicationContextAware应用场景及实现原理! - 程序员古德

ApplicationContextAware接口允许开发者在Bean中轻松获取到应用上下文ApplicationContext,这使得Bean能够灵活地访问Spring容器中的其他Bean和资源,增强了组件间的解耦和可扩展性。

但是,过度使用ApplicationContextAware可能导致代码与Spring容器紧密耦合,降低了代码的可移植性和可测试性。

关注我,每天学习互联网编程技术 - 程序员古德

END!
END!
END!

往期回顾

精品文章

Spring揭秘:@import注解应用场景及实现原理!

Java并发基础:原子类之AtomicMarkableReference全面解析!

Java并发基础:concurrent Flow API全面解析

Java并发基础:CopyOnWriteArraySet全面解析

Java并发基础:ConcurrentSkipListMap全面解析

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

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

相关文章

腾讯云学生服务器详细介绍_学生服务器价格_学生机申请流程

2024年腾讯云学生服务器优惠活动「云校园」&#xff0c;学生服务器优惠价格&#xff1a;轻量应用服务器2核2G学生价30元3个月、58元6个月、112元一年&#xff0c;轻量应用服务器4核8G配置191.1元3个月、352.8元6个月、646.8元一年&#xff0c;CVM云服务器2核4G配置842.4元一年&…

Java开发从入门到精通(一):Java的基础语法高阶

Java大数据开发和安全开发 &#xff08;一)Java的流程控制1.1 分支语句1.1.1 IF分支语句第一种IF语句第二种IF-ELSE语句第三种IF-ELSE IF-ELSE语句if语句使用的几个常见问题 1.1.2 switch分支语句switch分支的执行流程switch分支的导学案例:电子备忘录if、switch的比较&#xf…

关于JavaScript你该知道的(错误)和不知道的(技巧)

关于JS你该知道的(错误)和不知道的(技巧) 你该知道的(容易犯的错误) 忽略异步函数// Incorrect: Ignoring the asynchronous nature of setTimeout console.log("Start"); setTimeout(() => console.log("Timeout"), 0); console.log("End&q…

【实验】学习实验debug,以及经验感悟

记录两次独立解决问题的过程&#xff1a; 目前来看&#xff0c;问题分为几种&#xff1a; 抄代码的时候抄错了&#xff0c;比如dim1写成dim0这种 逻辑错误&#xff0c;如果两份代码没什么差别的话&#xff0c;那么肯定是逻辑错误。 下面的两个问题都是逻辑错误&#xff0c;因为…

【C++精简版回顾】21.迭代器(未完成)

1.什么是迭代器&#xff1f; 用来遍历容器&#xff0c;访问容器数据。 2.迭代器使用 1.初始化 //初始化 list<int> mylist;//list的整数对象 list<int>::iterator iter;//list内部类&#xff0c;迭代器对象(正向输出) list<int>::reverse_iterator riter;//…

Android使用WebView打开网页链接(内嵌H5网页)的两种方式之一

发布Android应用&#xff0c;除了用原生开发外&#xff0c;更多是采用内嵌H5网页的方式来做&#xff0c;便于更新以及多平台使用。 一、第一种方式是直接通过WebView打开外部H5链接。 新建Android工程 直接创建一个工程&#xff0c;点击运行就可以了&#xff0c;打开是个空页…

PaddlePaddle----基于paddlehub的OCR识别

Paddlehub介绍 PaddleHub是一个基于PaddlePaddle深度学习框架开发的预训练模型库和工具集&#xff0c;提供了丰富的功能和模型&#xff0c;包括但不限于以下几种&#xff1a; 1.文本相关功能&#xff1a;包括文本分类、情感分析、文本生成、文本相似度计算等预训练模型和工具。…

基于springboot精品在线试题库系统论文

摘 要 使用旧方法对作业管理信息进行系统化管理已经不再让人们信赖了&#xff0c;把现在的网络信息技术运用在作业管理信息的管理上面可以解决许多信息管理上面的难题&#xff0c;比如处理数据时间很长&#xff0c;数据存在错误不能及时纠正等问题。这次开发的精品在线试题库系…

022—pandas 根据时间段转换为各小时的秒数

前言 本例中&#xff0c;有一些时间段数据&#xff0c;需要将这些时间段里的时间以小时为分组&#xff0c;将24个小时段中每个小时所占用的秒数计算出来。 需求&#xff1a; 以第一条数据为例&#xff0c;它所在两个小时&#xff0c;7点段占用24分钟15秒&#xff0c;8点段54…

【一起学习Arcade】(5):属性规则实例_计算规则

属性规则可改善地理数据库数据集的编辑体验并提高数据完整性。 这些规则均为用户定义的规则&#xff0c;可用于自动填充属性、在编辑操作期间限制无效编辑&#xff0c;以及对现有要素执行质量保证检查。 属性规则分为3类&#xff1a;计算、约束和验证。 这一篇介绍计算规则&…

光谱整形1

华为张德江&#xff1a;下一代光传送网将走向400G80波WDM系统_通信世界网 (cww.net.cn) 张德江指出&#xff0c;400G WDM系统具有三大基本特征&#xff1a;支持400G80波&#xff0c;单纤32T超大容量&#xff0c;传输距离与100G相当&#xff1b;支持32维以上的光交叉&#xff1…

为什么不从独立服务器中转向云或其他方案呢?

传统的专用服务器&#xff0c;如香港服务器租赁、重庆服务器租赁等&#xff0c;是最强大、最稳定的业务托管类型之一。您将获得比任何其他托管计划更多的管理权限和卓越的性能&#xff0c;并且您可以控制整个服务器上的几乎所有内容。 当然&#xff0c;专用服务器也是在线业务…

昏暗场景增强-低照度增强-弱光增强(附代码)

引言 随着现代科技的发展&#xff0c;图像采集设备已经渗透到生活的方方面面&#xff0c;然而在昏暗场景、低照度或弱光条件下&#xff0c;图像的质量往往受到严重影响&#xff0c;表现为亮度不足、对比度低下、色彩失真以及细节丢失等问题。这类图像对于人眼识别和计算机视觉…

大数据冷热分离方案

数据冷热分离方案 1、背景 ​ 随着业务的发展&#xff0c;在线表中的数据会逐渐增加。常规业务都有冷热数据现象明显的特性&#xff08;需要访问的都是近期产生的热数据&#xff1b;时间久远的冷数据出于备份、备案溯源等诉求会进行在线保留&#xff09;。在业务表数据 量可控…

自动化测试之web自动化(Selenium)

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

基础小白快速入门并行计算------>我们为什么要学习并行计算

什么是并行计算&#xff1f; 随着计算机的不断发展&#xff0c;我们处理的数据不断变多&#xff0c;需要更大得到处理能力、我们希望计算机有着更大更强壮的计算能力&#xff0c;由于cpu的运行能力有限&#xff0c;我们便想到了将多个cpu进行串联计算问题&#xff0c;这也就是我…

第五十二回 戴宗二取公孙胜 李逵独劈罗真人-飞桨AI框架安装和使用示例

吴用说只有公孙胜可以破法术&#xff0c;于是宋江请戴宗和李逵去蓟州。两人听说公孙胜的师傅罗真人在九宫县二仙山讲经&#xff0c;于是到了二仙山&#xff0c;并在山下找到了公孙胜的家。 两人请公孙胜去帮助打高唐州&#xff0c;公孙胜说听师傅的。罗真人说出家人不管闲事&a…

接口测试,后端接口还没开发完,如何测?解决看这一篇就够了......

前言 在测试的时候经常会碰到后端开发工程师的接口还没有开发完成&#xff0c;但是测试任务已经分配过来。没有接口怎么测试呢&#xff1f; 测试人员可以通过 mock server 自己去造一个接口来访问。mock server 可用于模拟真实的接口。收到请求时&#xff0c;它会根据配置返回…

【24春招/简历】如果技术和学历不行,如何包装自己在春招中占得先机?突出你的亮点!

面试讲什么 学历&#xff1a; 行情 要美化&#xff08;吹牛&#xff09; 面试很好 技术能力 让面试官知道你会哪些技术&#xff0c;尽量细节 “熟悉spring” > ioc流程&#xff0c;Bean的生命周期&#xff0c;循环依赖&#xff0c;常见注解 熟悉redis > 缓存穿透&…

2024年AI辅助研发:科技遇上创意,无限可能的绽放

码到三十五 &#xff1a; 个人主页 心中有诗画&#xff0c;指尖舞代码&#xff0c;目光览世界&#xff0c;步履越千山&#xff0c;人间尽值得 ! 随着人工智能技术的持续突破与深度融合&#xff0c;2024年AI辅助研发正以前所未有的速度和规模&#xff0c;引领着科技界和工业界…