【Spring Boot 3】获取已注入的Bean
【Spring Boot 3】获取已注入的Bean
- 背景
- 介绍
- 开发环境
- 开发步骤及源码
- 工程目录结构
- 总结
背景
软件开发是一门实践性科学,对大多数人来说,学习一种新技术不是一开始就去深究其原理,而是先从做出一个可工作的DEMO入手。但在我个人学习和工作经历中,每次学习新技术总是要花费或多或少的时间、检索不止一篇资料才能得出一个可工作的DEMO,这占用了我大量的时间精力。因此本文旨在通过一篇文章即能还原出可工作的、甚至可用于生产的DEMO,期望初学者能尽快地迈过0到1的这一步骤,并在此基础上不断深化对相关知识的理解。
为达以上目的,本文会将开发环境、工程目录结构、开发步骤及源码尽量全面地展现出来,文字描述能简则简,能用代码注释的绝不在正文中再啰嗦一遍,正文仅对必要且关键的信息做重点描述。
介绍
本文介绍开发Spring Boot应用如何获取已注入的Bean实例。
开发环境
分类 | 名称 | 版本 |
---|---|---|
操作系统 | Windows | Windows 11 |
JDK | Oracle JDK | 21.0.1 |
IDE | IntelliJ IDEA | 2023.3.4 |
构建工具 | Apache Maven | 3.9.6 |
开发步骤及源码
1> 创建Maven工程,添加依赖。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>com.jiyongliang</groupId><artifactId>springboot3-bean</artifactId><version>0.0.1</version></parent><artifactId>springboot3-bean-obtain</artifactId><properties><java.version>21</java.version><maven.compiler.source>21</maven.compiler.source><maven.compiler.target>21</maven.compiler.target><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><spring-boot.version>3.2.2</spring-boot.version><lombok.version>1.18.30</lombok.version></properties><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${spring-boot.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>${lombok.version}</version></dependency></dependencies><build><pluginManagement><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>${spring-boot.version}</version></plugin></plugins></pluginManagement><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build>
</project>
2> 定义SpringBoot应用启动类。
package org.example.springboot;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class SpringBoot3BeanObtainApplication {public static void main(String[] args) {SpringApplication.run(SpringBoot3BeanObtainApplication.class, args);}
}
3> 定义获取已注入Bean的核心类。
package org.example.springboot.manager;import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;@Component
@Getter
@Slf4j
public class BeanManager {private final ApplicationContext applicationContext;public BeanManager(ApplicationContext applicationContext) {this.applicationContext = applicationContext;}/*** 通过Bean名称获取*/public Object getBean(String name) {try {return this.applicationContext.getBean(name);} catch (NoSuchBeanDefinitionException e) {log.error(e.getMessage());return null;}}/*** 通过Bean类型获取* 如果存在同一类型的多个Bean实例则会抛出NoSuchBeanDefinitionException,异常信息:expected single matching bean but found 2*/public <T> T getBean(Class<T> clazz) {try {return this.applicationContext.getBean(clazz);} catch (NoSuchBeanDefinitionException e) {log.error(e.getMessage());return null;}}/*** 通过Bean名称和类型获取*/public <T> T getBean(String name, Class<T> clazz) {try {return this.applicationContext.getBean(name, clazz);} catch (NoSuchBeanDefinitionException e) {log.error(e.getMessage());return null;}}
}
4> 定义测试Bean。
package org.example.springboot.bean;import lombok.AllArgsConstructor;
import lombok.Data;@AllArgsConstructor
@Data
public class CustomBean {private Integer id;private String name;
}
5> 配置注入Bean。
package org.example.springboot.config;import org.example.springboot.bean.CustomBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class CustomBeanConfig {@Bean("beanX")public CustomBean beanX() {return new CustomBean(1, "Bean-X");}@Bean("beanY")public CustomBean beanY() {return new CustomBean(2, "Bean-X");}
}
6> 创建单元测试。
package org.example.springboot.manager;import jakarta.annotation.Resource;
import org.assertj.core.api.Assertions;
import org.example.springboot.bean.CustomBean;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest
class BeanManagerTests {@AutowiredBeanManager beanManager;@Resource(name = "beanX")CustomBean beanX;@Resource(name = "beanY")CustomBean beanY;@Testvoid test() {System.out.println("Test get bean by name");Assertions.assertThat(beanManager.getBean("beanX")).isSameAs(beanX);Assertions.assertThat(beanManager.getBean("beanY")).isSameAs(beanY);System.out.println("Test get bean by type");Assertions.assertThat(beanManager.getBean(CustomBean.class)).isNull();System.out.println("Test get bean by name and type");Assertions.assertThat(beanManager.getBean("beanX", CustomBean.class)).isSameAs(beanX);Assertions.assertThat(beanManager.getBean("beanY", CustomBean.class)).isSameAs(beanY);}
}
7> 单元测试结果。
单元测试日志:
Test get bean by name
Test get bean by type
2024-03-08T20:31:34.845+08:00 ERROR 18872 --- [ main] o.e.springboot.manager.BeanManager : No qualifying bean of type 'org.example.springboot.bean.CustomBean' available: expected single matching bean but found 2: beanX,beanY
Test get bean by name and type
从日志中可以看出,测试根据类型获取注入的Bean时抛出了异常,因为找到2个同样类型的Bean,无法判断应该返回哪个Bean,因此通过类型获取Bean时,有且仅有一个类型匹配的Bean才会正常返回。
工程目录结构
总结
测试用的Bean和配置注入放在 src/test
目录下是为了辅助测试。
相关文章:

【Spring Boot 3】获取已注入的Bean
【Spring Boot 3】获取已注入的Bean 背景介绍开发环境开发步骤及源码工程目录结构总结 背景 软件开发是一门实践性科学,对大多数人来说,学习一种新技术不是一开始就去深究其原理,而是先从做出一个可工作的DEMO入手。但在我个人学习和工作经历…...
C# 对于点位置的判断
1.判断点是否在一群点内部 要判断一个点是否在一个由多个点围成的多边形内部(例如一圈点),可以使用射线法(Ray Casting Algorithm)来实现。以下是一个简单的 C# 实现示例 using System;public class Point {public d…...

最新CLion + STM32 + CubeMX 开发环境搭建
网上有不少相关教程,但都是基于老版本Clion,新版有一些改变,但整体是简单了。 PS:本教程基于CLion 2023.3.4 安装所需工具参考:Clion搭建stm32开发环境(STM32F103C8T6),有这一篇就够…...
【Python3】观察者模式
观察者模式(Observer Pattern)是一种常见的设计模式,用于定义对象之间的一对多依赖关系,使得一个对象的状态改变能够通知所有依赖于它的对象并自动更新。 在观察者模式中,有两个核心角色: Subject…...

HTML5 Web Worker之性能优化
描述 由于 JavaScript 是单线程的,当执行比较耗时的任务时,就会阻塞主线程并导致页面无法响应,这就是 Web Workers 发挥作用的地方。它允许在一个单独的线程(称为工作线程)中执行耗时的任务。这使得 JavaScript 代码可…...

应对恶意IP攻击的有效方法
在当今数字化时代,网络攻击已经成为了互联网安全的重大挑战之一。恶意IP攻击是网络安全领域中的一种常见威胁,它可能导致数据泄露、服务中断、系统瘫痪等严重后果。因此,有效地应对恶意IP攻击至关重要。IP数据云将深入探讨如何应对恶意IP攻击…...

如何使用“Docker registry创建本地仓库,在服务器之间进行文件push和pull”?
1.1、在服务器1,运行registry docker run -d -p 5000:5000 -v ${PWD}/registry:/var/lib/registry --restart always --name registry registry:2.7.11.2、编辑/etc/docker/daemon.json 文件, 192.168.xxx.xxx 换成你自己 registry 服务的地址 sudo na…...

Rocky Linux - Primavera P6 EPPM 安装及分享
引言 继上一期发布的Redhat Linux版环境发布之后,近日我又制作了基于Rocky Enterprise Linux 的P6虚拟机环境,同样里面包含了全套P6 最新版应用服务 此虚拟机仅用于演示、培训和测试目的。如您在生产环境中使用此虚拟机,请先与Oracle Primav…...
API 管理调研
当前大部分团队内 API 管理都是依赖 Postman,postman最大的问题是共享问题,如果我要使用另外一个人已经调试好的 API 非常麻烦。因此,能实现协作的 API 管理将极大提升效率。 Yapi https://github.com/YMFE/yapi https://hellosean1025.gi…...

在centOS服务器安装docker,并使用docker配置nacos
遇到安装慢的情况可以优先选择阿里镜像 安装docker 更新yum版本 yum update安装所需软件包 yum install -y yum-utils device-mapper-persistent-data lvm2添加Docker仓库 yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.rep…...
JVM运行时数据区概述以及分别存放的内容
JVM的运行时数据区是JVM在执行Java程序时用于存储数据和状态信息的内存区域。它分为多个部分,每个部分都有其特定的作用和存放的内容。 1. 方法区(Method Area) 作用:方法区是所有线程共享的内存区域,用于存放已被虚…...
数据体系规范化
基础是标准化、规范化 建立数据仓库,面向主题的、集成的、相对稳定的、反映历史变化的数据集合,以支持管理决策decision making 大数据:大量volumn、多样variety、快速velocity、价值密度低value、准确性veracity、可视化visualization、合法性validity 多源数据、多样数…...

从政府工作报告探计算机行业发展
从政府工作报告中,我们可以深入洞察计算机行业在未来一年的发展趋势和政策导向。报告中明确提出了数字经济创新发展的重要性,以及制造业数字化转型、服务业数字化、智慧城市和数字乡村建设等关键任务,这些都为计算机行业提供了广阔的发展空间…...

【软件工具】网络性能测试工具 Iperf
Iperf 是一款专业的开源网络性能测试工具,它被广泛用于测量网络带宽、延迟、抖动和数据包丢失等网络性能指标,支持 TCP 和 UDP 等,可用于点对点或客户端-服务器等模式的网络测试。 软件获取 官方下载地址:https://iperf.fr/iper…...

Day32:安全开发-JavaEE应用Servlet路由技术JDBCMybatis数据库生命周期
目录 JavaEE-HTTP-Servlet&路由&周期 JavaEE-数据库-JDBC&Mybatis&库 思维导图 Java知识点: 功能:数据库操作,文件操作,序列化数据,身份验证,框架开发,第三方库使用等. 框架…...
C语言下使用SQL语言
需头文件:#include<sqlite.h>---需下载 1.sqlite3_open int sqlite3_open( const char *filename, /* Database filename (UTF-8) */ sqlite3 **ppDb /* OUT: SQLite db handle */ ); 功能: 打开数据库文件(…...
Gitea相关漏洞
Go代码审计:Gitea远程命令执行漏洞链_新闻中心-网盾网络安全培训学校 Vulhub靶场gitea-1.4远程代码执行漏洞复现_gitea 漏洞-CSDN博客...

基于深度学习的图像去雨去雾
基于深度学习的图像去雨去雾 文末附有源码下载地址 b站视频地址: https://www.bilibili.com/video/BV1Jr421p7cT/ 基于深度学习的图像去雨去雾,使用的网络为unet, 网络代码: import torch import torch.nn as nn from torchsumm…...
使用JS的for循环实现九九乘法表
九九乘法表是我们在学习基础数学时经常会遇到的一个概念。在编程中,使用循环结构来实现九九乘法表是一个很好的练习。下面,我将详细介绍如何使用JavaScript的for循环来实现九九乘法表。 首先,我们需要理解for循环的基本结构。在JavaScript中…...

Leetcode 70 爬楼梯
文章目录 1. 题目描述2. 我的尝试 1. 题目描述 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢? 示例 1: 输入:n 2 输出:2 解释:有两种方法可以爬到…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?
编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

docker详细操作--未完待续
docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...

简易版抽奖活动的设计技术方案
1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器
——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的一体化测试平台,覆盖应用全生命周期测试需求,主要提供五大核心能力: 测试类型检测目标关键指标功能体验基…...

Swift 协议扩展精进之路:解决 CoreData 托管实体子类的类型不匹配问题(下)
概述 在 Swift 开发语言中,各位秃头小码农们可以充分利用语法本身所带来的便利去劈荆斩棘。我们还可以恣意利用泛型、协议关联类型和协议扩展来进一步简化和优化我们复杂的代码需求。 不过,在涉及到多个子类派生于基类进行多态模拟的场景下,…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...
Typeerror: cannot read properties of undefined (reading ‘XXX‘)
最近需要在离线机器上运行软件,所以得把软件用docker打包起来,大部分功能都没问题,出了一个奇怪的事情。同样的代码,在本机上用vscode可以运行起来,但是打包之后在docker里出现了问题。使用的是dialog组件,…...

短视频矩阵系统文案创作功能开发实践,定制化开发
在短视频行业迅猛发展的当下,企业和个人创作者为了扩大影响力、提升传播效果,纷纷采用短视频矩阵运营策略,同时管理多个平台、多个账号的内容发布。然而,频繁的文案创作需求让运营者疲于应对,如何高效产出高质量文案成…...

Unity中的transform.up
2025年6月8日,周日下午 在Unity中,transform.up是Transform组件的一个属性,表示游戏对象在世界空间中的“上”方向(Y轴正方向),且会随对象旋转动态变化。以下是关键点解析: 基本定义 transfor…...