ApplicationContextAware:Bean 的“上下文感知”超能力

  在 Spring Boot 的世界中,我们依赖依赖注入(DI)来管理 Bean 之间的关系。然而,有时我们需要 Bean 直接访问 Spring 应用上下文(ApplicationContext)来执行一些特殊操作。这时,ApplicationContextAware 接口就派上了用场。本文将深入探讨 ApplicationContextAware 在 Spring Boot 中的应用,揭示其工作原理,并分享一些最佳实践。

一、ApplicationContextAware 的作用:赋予 Bean “上下文感知”的能力

  ApplicationContextAware 是 Spring 框架中的一个接口,它允许 Bean 在初始化时获取到 Spring 应用上下文(ApplicationContext)。通过这个上下文,Bean 可以访问 Spring 容器的各种服务,例如:

  1. 获取其他 Bean 实例:当依赖注入无法满足需求时,手动获取需要的 Bean。
  2. 发布 Spring 应用事件:在 Bean中触发自定义事件,实现应用之间的解耦。
  3. 访问资源文件:获取配置文件、国际化资源等。
  4. 获取环境信息:读取系统属性、环境变量等。

二、ApplicationContextAware 的工作原理

2.1 接口定义:

package org.springframework.context;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.Aware;

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

2.2 Spring Boot 的处理:

  当 Spring Boot 容器启动并实例化一个实现了 ApplicationContextAware 接口的 Bean 时,它会在 Bean 的属性注入完成之后,调用 setApplicationContext() 方法,并将 ApplicationContext 实例作为参数传入。这意味着,在 setApplicationContext() 方法中,你可以安全地访问 Bean 的属性。

三、ApplicationContextAware 在 Spring Boot 中的应用场景

3.1 手动获取 Bean(不推荐):

  场景: 某些情况下,由于循环依赖或其他复杂因素,无法通过依赖注入获取到需要的 Bean。
  示例

@Component
public class MyBean implements ApplicationContextAware {

  private ApplicationContext applicationContext;

  @Override
  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
   this.applicationContext = applicationContext;
   }

  public void doSomething() {
      // 避免直接使用getBean, 如果可以使用依赖注入最好
      AnotherBean anotherBean = applicationContext.getBean(AnotherBean.class);
      anotherBean.doWork();
    }
}

  注意: 尽可能避免使用 ApplicationContextAware 手动获取 Bean。依赖注入通常是更优雅、更解耦的解决方案。

3.2 发布 Spring 应用事件:

  场景: 需要在 Bean 中触发自定义事件,实现应用组件之间的解耦。
  示例

@Component
public class MyBean implements ApplicationContextAware {

   private ApplicationContext applicationContext;
   private ApplicationEventPublisher publisher;

   @Override
   public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
       this.applicationContext = applicationContext;
       this.publisher= applicationContext; //ApplicationContext 也实现了ApplicationEventPublisher
   }

   public void doSomething() {
       publisher.publishEvent(new MyCustomEvent("触发自定义事件!"));
   }
}

  在 Spring Boot 中, 也可以直接注入 ApplicationEventPublisher 来发布事件。

3.3 访问资源文件:

  场景: 需要在 Bean 中访问 classpath 下的资源文件,例如配置文件、国际化文件等。
  示例

@Component
public class MyBean implements ApplicationContextAware {
    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    public void doSomething() throws IOException {
        Resource resource = applicationContext.getResource("classpath:myconfig.properties");
         try(InputStream inputStream = resource.getInputStream()){
                // 读取文件流
         }
    }
 }

3.4 获取环境信息:

  场景: 需要在 Bean 中访问 Spring Boot 的 Environment 对象,获取配置信息、系统属性、环境变量等。
  示例

@Component
public class MyBean implements ApplicationContextAware {

    private ApplicationContext applicationContext;
    private Environment environment;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
        this.environment = applicationContext.getEnvironment();
    }

    public void doSomething() {
        String appName = environment.getProperty("spring.application.name");
        System.out.println("Application Name: " + appName);
    }
}

  在 Spring Boot 中,也可以直接注入 Environment 对象

四、ApplicationContextAware 的最佳实践

  1. 优先依赖注入: 尽可能使用依赖注入来获取需要的 Bean,避免滥用 ApplicationContextAware。
  2. 避免直接操作Bean 容器: 尽量不要在 ApplicationContextAware 获取到的 ApplicationContext上进行复杂的 Bean 操作。
  3. 解耦: 对于复杂的逻辑,尽量将 ApplicationContextAware的使用封装起来,避免代码过于耦合。
  4. 测试: 在单元测试中,需要 Mock ApplicationContext,以保证测试的独立性。
  5. 注意生命周期: 确保在使用 ApplicationContext 时,容器已经完全启动,并且 Bean 已经初始化完成。
  6. 注意线程安全:如果您的应用程序是多线程的,请确保对ApplicationContext的操作是线程安全的。

五、ApplicationContextAware 的替代方案

  1. 依赖注入: 最常用的替代方案,Spring Boot 推荐使用依赖注入来管理 Bean 之间的关系。
  2. ApplicationEventPublisher: 用于发布应用事件,可以直接注入到 Bean 中。
  3. Environment:用于获取配置信息,可以直接注入到 Bean 中。
  4. ResourceLoader: 用于加载资源文件,可以直接注入到 Bean 中。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

python麻辣香锅菜品推荐

1.推荐算法概述 推荐算法出现得很早,最早的推荐系统是卡耐基梅隆大学推出的Web Watcher浏览器导航系统,可以根据当的搜索目标和用户信息,突出显示对用户有用的超链接。斯坦福大学则推出了个性化推荐系统LIRA.AT&T实验室于1997年提出基于协作过滤的个性化推荐系统…

利用大型语言模型在量化投资中实现自动化策略

“Automate Strategy Finding with LLM in Quant investment” 论文地址:https://arxiv.org/pdf/2409.06289 摘要 这个新提出的量化股票投资框架,利用大型语言模型(LLMs)与多智能体系统相结合的方法,通过LLMs从包括数…

JAVA:Spring Boot 实现责任链模式处理订单流程的技术指南

1、简述 在复杂的业务系统中,订单流程往往需要一系列的操作,比如验证订单、检查库存、处理支付、更新订单状态等。责任链模式(Chain of Responsibility)可以帮助我们将这些处理步骤分开,并且以链式方式处理每一个操作…

(开源)基于Django+Yolov8+Tensorflow的智能鸟类识别平台

1 项目简介(开源地址在文章结尾) 系统旨在为了帮助鸟类爱好者、学者、动物保护协会等群体更好的了解和保护鸟类动物。用户群体可以通过平台采集野外鸟类的保护动物照片和视频,甄别分类、实况分析鸟类保护动物,与全世界各地的用户&…

算法专题(三):二分查找

本篇还是像之前一样,以举例子的形式向大家讲解!每道题的题目均是传送门!点击跳转对应题! 目录 一、二分查找 1.1 题目 1.2 思路 1.3 代码实现 总结(模版) 朴素版: 二、在排序数组中查找…

C# OpenCvSharp 部署文档矫正,包括文档扭曲/模糊/阴影等情况

目录 说明 效果 模型 项目 代码 下载 参考 C# OpenCvSharp 部署文档矫正,包括文档扭曲/模糊/阴影等情况 说明 地址:https://github.com/RapidAI/RapidUnDistort 修正文档扭曲/模糊/阴影等情况,使用onnx模型简单轻量部署&#xff0c…

Excel 技巧15 - 在Excel中抠图头像,换背景色(★★)

本文讲了如何在Excel中抠图头像,换背景色。 1,如何在Excel中抠图头像,换背景色 大家都知道在PS中可以很容易抠图头像,换背景色,其实Excel中也可以抠简单的图,换背景色。 ※所用头像图片为百度搜索&#x…

吴恩达深度学习——神经网络介绍

文章内容来自BV11H4y1F7uH,仅为个人学习所用。 文章目录 什么是神经网络引入神经网络神经元激活函数ReLU隐藏单元 用神经网络进行监督学习监督学习与无监督学习举例 什么是神经网络 引入 已经有六个房子的数据集,横轴为房子大小,纵轴为房子…

xctf-comment(Intruder,git恢复,SQL注入,Hex解码)

这题是2018年网鼎杯真题,考察 Burp Suite 的 Intruder 模块去找用户密码,使用 githacker 恢复代码(githack不行),代码审计发现SQL二次注入,尝试SQL注入读取文件内容,读取的是/home/www/.bash_hi…

分布式系统通信解决方案:Netty 与 Protobuf 高效应用

分布式系统通信解决方案:Netty 与 Protobuf 高效应用 一、引言 在现代网络编程中,数据的编解码是系统设计的一个核心问题,特别是在高并发和低延迟的应用场景中,如何高效地序列化和传输数据对于系统的性能至关重要。随着分布式系…

C++《AVL树》

在之前的学习当中我们已经了解了二叉搜索树,并且我们知道二叉搜索树的查找效率是无法满足我们的要求,当二叉树为左或者右斜树查找的效率就很低下了,那么这本篇当中我们就要来学习对二叉搜索树进行优化的二叉树——AVL树。在此会先来了解AVL树…

ToDesk设置临时密码和安全密码都可以当做连接密码使用

ToDesk 在各领域办公都已经是非常常见了 为了安全 ToDesk 设置了连接密码,想连接 需要输入远程码和连接密码 我们刚打开 系统默认给我们用的是临时密码,安全性确实很强 和定时Tokey一样,固定时间切换。 但是 如果我们要经常连接这个电脑&a…

LLMs(大型语言模型)的多智能体:Auto-GPT

LLMs(大型语言模型)的多智能体:Auto-GPT 是指在一个系统中集成多个具有不同能力、角色和任务的智能体,这些智能体能够相互协作、沟通和交互,以共同完成复杂的任务或解决复杂的问题。每个智能体都可以被视为一个独立的实体,具有自己的策略、目标和知识库,通过相互之间的…

【Linux环境变量与命令行参数】常见环境变量 | 环境变量的全局属性 | 命令行参数

前言 本文中主要介绍PATH、HOME、SHELL、HISTSIZE这4个环境变量,其中详细介绍PATH。并理解环境变量的全局属性--环境变量可以被子进程继承,这里要注意和C中的继承进行区分。其次,介绍命令行参数--mian函数的参数。 1.环境变量的基本概念 在…

【Python】函数(二)

链式调用 # 判定是否是奇数 def isOdd(num):if num % 2 0:return Falseelse:return Trueresult isOdd(10) print(result)实际上也可以简化写作 print(isOdd(10))把一个函数的返回值, 作为另一个函数的参数, 这种操作称为 链式调用 嵌套调用 函数内部还可以调用其他的函数…

【Elasticsearch 】 聚合分析:桶聚合

🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编…

学习ASP.NET Core的身份认证(基于JwtBearer的身份认证7)

本文验证基于请求头中传递token信息的认证方式,webapi项目的控制器类中新建如下函数,仅通过验证的客户端能调用,需要客户端请求在Header中添加’Authorization’: Bearer token’的键值对且通过token验证后才能调用。 [Authorize] [HttpGet]…

游戏AI,让AI 玩游戏有什么作用?

让 AI 玩游戏这件事远比我们想象的要早得多。追溯到 1948 年,图灵和同事钱伯恩共同设计了国际象棋程序 Turochamp。之所以设计这么个程序,图灵是想说明,机器理论上能模拟人脑能做的任何事情,包括下棋这样复杂的智力活动。 可惜的是…

9. 神经网络(一.神经元模型)

首先,先看一个简化的生物神经元结构: 生物神经元有多种类型,内部也有复杂的结构,但是可以把单个神经元简化为3部分组成: 树突:一个神经元往往有多个树突,用于接收传入的信息。轴突:…

Docker可视化管理工具Portainer

Portainer简介 Portainer 是一个轻量级的、开源的容器管理工具,提供了一个直观的 Web 用户界面(UI),用于管理 Docker 和 Kubernetes 环境。它简化了容器的部署、监控和管理,特别适合不熟悉命令行操作的用户或团队。 …