SpringBoot获取bean的几种方式
目录
一、BeanFactory与ApplicationContext的区别
二、通过BeanFactory获取
三、通过BeanFactoryAware获取
四、启动获取ApplicationContext
五、通过继承ApplicationObjectSupport
六、通过继承WebApplicationObjectSupport
七、通过WebApplicationContextUtils
八、通过ApplicationContextAware
九、通过ContextLoader
十、通过BeanFactoryPostProcessor
十一、通过工具类获取
一、BeanFactory与ApplicationContext的区别
BeanFactory是Spring框架的基础设施,面向Spring本身。ApplicationContext则面向使用Spring框架的开发者,几乎所有的应用场景都可以直接使用ApplicationContext,而非底层的BeanFactory。
ApplicationContext的初始化和BeanFactory有一个重大的区别:
BeanFactory在初始化容器时,并未实例化Bean,直到第一次访问某个Bean时才实例目标Bean。这样,我们就不能发现一些存在的Spring的配置问题。如果Bean的某一个属性没有注入,BeanFacotry加载后,直至第一次使用调用getBean方法才会抛出异常。
而ApplicationContext则在初始化应用上下文时就实例化所有单实例的Bean,相对应的,ApplicationContext的初始化时间会比BeanFactory长一些。
二、通过BeanFactory获取
通过BeanFactory来获取Bean。
基于xml配置文件:(不推荐使用)
BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("applicationContext.xml"));User user = (User) beanFactory.getBean("user");
三、通过BeanFactoryAware获取
获取BeanFactory实例最简单的方式就是实现BeanFactoryAware接口。
BeanFactoryAware接口源码:
public interface BeanFactoryAware extends Aware {
?/**
??* 初始化回调方法,Spring会自动将BeanFactory注入进去,接收之后即可使用BeanFactory
??*/
?void setBeanFactory(BeanFactory beanFactory) throws BeansException;
}
BeanFactoryAware属于org.springframework.beans.factory.Aware根标记接口,使用setter注入来在应用程序上下文启动期间获取对象。Aware接口是回调,监听器和观察者设计模式的混合,它表示Bean有资格通过回调方式被Spring容器通知。
示例如下:
@Component
public class BeanFactoryHelper implements BeanFactoryAware {?private static BeanFactory beanFactory;?/**
??* 重写 BeanFactoryAware 接口的方法
??* @param beanFactory :参数赋值给本地属性之后即可使用 BeanFactory
??* @throws BeansException BeansException
??*/
?@Override
?public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
??BeanFactoryHelper.beanFactory = beanFactory;
?}?/**
??* 根据名称获取容器中的对象实例
??* @param beanName :注入的实例必须已经存在容器中,否则抛异常:NoSuchBeanDefinitionException
??* @return Object
??*/
?public static Object getBean(String beanName) {
??return beanFactory.getBean(beanName);
?}?/**
??* 根据 class 获取容器中的对象实例
??* @param requiredType :被注入的必须已经存在容器中,否则抛异常:NoSuchBeanDefinitionException
??* @param <T> Class
??* @return 对象
??*/
?public static <T> T getBean(Class<T> requiredType) {
??return beanFactory.getBean(requiredType);
?}?/**
??* 判断 spring 容器中是否包含指定名称的对象
??* @param beanName bean名称
??* @return 是否存在
??*/
?public static boolean containsBean(String beanName) {
??return beanFactory.containsBean(beanName);
?}?//其它需求皆可参考 BeanFactory 接口和它的实现类}
上述基于BeanFactoryAware的特性,获得了BeanFactory,然后再通过BeanFactory来获得指定的Bean。
四、启动获取ApplicationContext
在项目启动时先获取ApplicationContext对象,然后将其存储在一个地方,以便后续用到时进行使用。
这里提供两种场景的获取:
1.基于xml配置bean的形式,适用于比较古老的项目,已经很少使用了;
2.基于SpringBoot启动时获取ApplicationContext对象;
基于xml的形式实现:
// 其中applicationContext.xml 为配置容器的xml,不过现在一般很少使用了
ApplicationContext ac = new FileSystemXmlApplicationContext("applicationContext.xml");
基于SpringBoot启动实现:
@SpringBootApplication
public class ExampleApplication {????public static void main(String[] args) {
????????// 启动时,保存上下文,并保存为静态
????????ConfigurableApplicationContext ac = SpringApplication.run(ExampleApplication.class, args);
????????SpringContextUtil.setApplicationContext(ac);
????}
}
对应的SpringContextUtil类如下:
public class SpringContextUtil1 {????private static ApplicationContext ac;????public static <T>? T getBean(String beanName, Class<T> clazz) {
????????T bean = ac.getBean(beanName, clazz);
????????return bean;
????}????public static void setApplicationContext(ApplicationContext applicationContext){
????????ac = applicationContext;
????}}
五、通过继承ApplicationObjectSupport
此种方式依旧是先获得ApplicationContext容器,然后从中获取Bean对象,只不过是基于继承ApplicationObjectSupport类实现的。
具体实现代码:SpringContextUtil类需要实例化。
@Component
public class SpringContextUtil extends ApplicationObjectSupport {?public <T> T getBean(Class<T> clazz) {
??ApplicationContext ac = getApplicationContext();
??if(ac == null){
???return null;
??}
??return ac.getBean(clazz);
?}
}
ApplicationObjectSupport类图入下,我们看到它实现了ApplicationContextAware接口,在Spring容器初始化过程中回调方法setApplicationContext来完成ApplicationContext的赋值。

六、通过继承WebApplicationObjectSupport
WebApplicationObjectSupport是ApplicationObjectSupport的一个实现类,提供了Web相关的支持。实现原理与ApplicationObjectSupport一样。
具体实现代码如下:
@Component
public class SpringContextUtil extends WebApplicationObjectSupport {?public <T> T getBean(Class<T> clazz) {
??ApplicationContext ac = getApplicationContext();
??if(ac == null)
???return null;
??}
??return ac.getBean(clazz);
?}
}
通过类图我们可以看到它是ApplicationObjectSupport的实现子类,此方式除了继承对象不同外,没有其他区别,都是基于getApplicationContext方法来获取。
七、通过WebApplicationContextUtils
Spring提供了工具类WebApplicationContextUtils,通过该类可获取WebApplicationContext对象。
具体实现代码如下:
public class SpringContextUtil2 {?public static <T> T getBean(ServletContext request, String name, Class<T> clazz){
??WebApplicationContext webApplicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(request);
??// 或者
??WebApplicationContext webApplicationContext1 = WebApplicationContextUtils.getWebApplicationContext(request);
//??????? webApplicationContext1.getBean(name, clazz)??T bean = webApplicationContext.getBean(name, clazz);
??return bean;
?}
}
这个方法很常见于SpringMVC构建的Web项目中,适用于Web项目的B/S结构。
八、通过ApplicationContextAware
通过实现ApplicationContextAware接口,在Spring容器启动时将ApplicationContext注入进去,从而获取ApplicationContext对象,这种方法也是常见的获取Bean的一种方式,推荐使用。
具体实现代码如下:
@Component
public class SpringContextUtil3 implements ApplicationContextAware {?private static ApplicationContext ac;?@Override
?public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
??ac = applicationContext;
?}?public static <T> T getBean(Class<T> clazz) {
??T bean = ac.getBean(clazz);
??return bean;
?}}
九、通过ContextLoader
使用ContextLoader提供的getCurrentWebApplicationContext方法,也是常用的获取WebApplicationContext的一种方法。
具体实现代码如下:
WebApplicationContext wac = ContextLoader.getCurrentWebApplicationContext();
wac.getBean(beanID);
该方法常见于SpringMVC实现的Web项目中。该方式是一种不依赖于Servlet,不需要注入的方式。但是需要注意一点,在服务器启动时和Spring容器初始化时,不能通过该方法获取Spring容器。
十、通过BeanFactoryPostProcessor
Spring工具类,方便在非Spring管理环境中获取Bean。
@Component
public final class SpringUtils implements BeanFactoryPostProcessor{????/** Spring应用上下文环境 */
????private static ConfigurableListableBeanFactory beanFactory;????@Override
????public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException{
????????SpringUtilsS.beanFactory = beanFactory;
????}????/**
?????* 获取对象
?????*
?????* @param name
?????* @return Object 一个以所给名字注册的bean的实例
?????* @throws BeansException
?????*
?????*/
????@SuppressWarnings("unchecked")
????public static <T> T getBean(String name) throws BeansException{
????????return (T) beanFactory.getBean(name);
????}????/**
?????* 获取类型为requiredType的对象
?????*
?????* @param clz
?????* @return
?????* @throws BeansException
?????*
?????*/
????public static <T> T getBean(Class<T> clz) throws BeansException{
????????T result = (T) beanFactory.getBean(clz);
????????return result;
????}????/**
?????* 如果BeanFactory包含一个与所给名称匹配的bean定义,则返回true
?????*
?????* @param name
?????* @return boolean
?????*/
????public static boolean containsBean(String name){
????????return beanFactory.containsBean(name);
????}????/**
?????* 判断以给定名字注册的bean定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException)
?????*
?????* @param name
?????* @return boolean
?????* @throws NoSuchBeanDefinitionException
?????*
?????*/
????public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException{
????????return beanFactory.isSingleton(name);
????}????/**
?????* @param name
?????* @return Class 注册对象的类型
?????* @throws NoSuchBeanDefinitionException
?????*
?????*/
????public static Class<?> getType(String name) throws NoSuchBeanDefinitionException{
????????return beanFactory.getType(name);
????}????/**
?????* 如果给定的bean名字在bean定义中有别名,则返回这些别名
?????*
?????* @param name
?????* @return
?????* @throws NoSuchBeanDefinitionException
?????*
?????*/
????public static String[] getAliases(String name) throws NoSuchBeanDefinitionException{
????????return beanFactory.getAliases(name);
????}????/**
?????* 获取aop代理对象
?????*
?????* @param invoker
?????* @return
?????*/
????@SuppressWarnings("unchecked")
????public static <T> T getAopProxy(T invoker){
????????return (T) AopContext.currentProxy();
????}}
其中ConfigurableListableBeanFactory接口,也属于BeanFactory的子接口。
十一、通过工具类获取
RequestContextUtils.findWebApplicationContext(HttpServletRequest request)WebApplicationContextUtils.getWebApplicationContext(ServletContext sc)
controller中获取:
public String test(HttpServletRequest request,HttpServletRequest response) {WebApplicationContext wc = RequestContextUtils.findWebApplicationContext(request);wc.getBean("beanName");WebApplicationContext wc2 = WebApplicationContextUtils.getWebApplicationContext(request.getServletContext());wc2.getBean("beanName");
}
在service中或者其他后端服务中获取:
HttpServletRequest request = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest();
WebApplicationContext wc = RequestContextUtils.findWebApplicationContext(request);
WebApplicationContext wc2 = WebApplicationContextUtils.getWebApplicationContext(request.getServletContext());wc.getBean("beanName");
wc2.getBean("beanName");
相关文章:
SpringBoot获取bean的几种方式
目录 一、BeanFactory与ApplicationContext的区别 二、通过BeanFactory获取 三、通过BeanFactoryAware获取 四、启动获取ApplicationContext 五、通过继承ApplicationObjectSupport 六、通过继承WebApplicationObjectSupport 七、通过WebApplicationContextUtils 八、通…...
Debian12 安装配置 ODBC for GaussDB
第一步 apt install -y unixodbc 第二步下载 dws_8.2.x_odbc_driver_for_x86_redhat.zip 到 /tmp,之后 cd /tmp unzip dws_8.2.x_odbc_driver_for_x86_redhat.zip cp lib/* /usr/local/lib cp odbc/lib/* /usr/local/lib echo /usr/local/lib >> /etc/ld…...
空中绘图板:用 Mediapipe 和 OpenCV 实现的创新手势识别应用
在这个数字化飞速发展的时代,手势识别技术正逐渐走入我们的日常生活,从智能家居到增强现实,无处不在。而今天,我将与大家分享一个充满创意和趣味的项目——空中绘图板。这个项目利用了强大的 Mediapipe 库和 OpenCV,实…...
讲一个自己写的 excel 转 html 的 java 工具
由来 这是一个从开发需求中诞生的工具,在工作中因为有一个 excel 转 html 的任务,又没找到一个专门做这方面的工具(其他工具几乎都是简单的转换,无法还原 excel 样式,而且转换的宽高有点儿差距)࿰…...
前端往后端传递参数的方式有哪些?
文章目录 1. URL 参数1.1. 查询参数(Query Parameters)1.2. 路径参数(Path Parameters) 2. 请求体(Request Body)2.1. JSON 数据2.2. 表单数据2.3. 文件上传 3. 请求头(Headers)3.1. 自定义请求…...
Vue axios 异步请求,请求响应拦截器
在 Vue.js 中使用 axios 进行网络请求是非常常见的做法,因为它提供了比原生的 Fetch API 更丰富的功能,并且更易于处理错误和配置。结合 Axios 的拦截器功能,你可以对所有的请求或响应进行预处理,比如添加认证头信息、统一处理错误…...
yarn install 安装报错:Workspaces can only be enabled in private projects.
在本地运行项目的时候,使用yarn install 安装模块依赖的时候,遇到报错:Workspaces can only be enabled in private projects. 一、原因分析 报这个错误是因为你使用了yarn的workspace,但并未将工程标记为private。 二、解决办法 …...
http 请求总结get
关于get请求传递body的问题 错误代码 有400 , 415 等情况 <!doctype html><html lang"zh"><head><title>HTTP Status 400 – 错误的请求</title><style type"text/css">body {font-family:Tahoma,Arial,sans-seri…...
TCP 和 UDP 的区别:解析网络传输协议
引言 在计算机网络的世界中,TCP(Transmission Control Protocol,传输控制协议)和 UDP(User Datagram Protocol,用户数据报协议)是两种极为重要且应用广泛的传输层协议。它们在功能、特性以及适…...
【已解决】pyinstaller打包ico图片报错:OSError: [WinError 225] 无法成功完成操作,因为文件包含病毒或潜在的垃圾软件。
起因: pyinstaller加上 --icon 参数打包时报错。 命令如下: 解决: 关闭 Windows 的病毒防护即可,步骤如下。 点屏幕右下角通知栏,进入“病毒和威胁防护”: 打开: 关闭实时保护(…...
SpringBoot项目配置文件的优先级
从外部讲 内部讲 所以优先级是:外部的config里的application.yml最高 然后是外部与jar包同目录下的application.yml 再到内部的classpath下config下的application.yml 最后到classpath下的application.yml 最后来个优先级最高的 启动时候 指定spring.config.location…...
JS中类型化数组(Typed Arrays)详解和常见应用场景
在JavaScript中,类型化数组(Typed Arrays) 是用于处理二进制数据的对象。它们允许我们以一种高效的方式操作和存储大量的数值数据,特别适合处理类似于图像、音频、视频等场景的原始二进制数据。 类型化数组的基本概念 类型化数组…...
虚幻引擎是什么?
Unreal Engine,是一款由Epic Games开发的游戏引擎。该引擎主要是为了开发第一人称射击游戏而设计,但现在已经被成功地应用于开发模拟游戏、恐怖游戏、角色扮演游戏等多种不同类型的游戏。虚幻引擎除了被用于开发游戏,现在也用于电影的虚拟制片…...
LabVIEW生物医学信号虚拟实验平台
介绍了一款基于LabVIEW的多功能生物医学信号处理实验平台的设计和实现。平台通过实践活动加强学生对理论的理解和应用能力,特别是在心电图(ECG)和脑电图(EEG)的信号处理方面。实验平台包括信号的滤波、特征提取和频谱分析等功能,能直观体验和掌握生物医学…...
【软件工程】十万字知识点梳理 | 期末复习专用
原创文章,禁止转载。 文章目录 图CRC卡片用例图类图状态图活动图泳道图软件质量因素自顶向下集成自底向上集成人员与工作量之间的关系时序图关键路径软件结构基本路径测试判定表数据流图(DFD)体系结构设计问题数据字典挣值分析等价划分程序流程图PAD | N-S燃尽图甘特图对象模…...
Android --- 在AIDL进程间通信中,为什么使用RemoteCallbackList 代替 ArrayList?
1.RemoteCallbackList vs ArrayList RemoteCallbackList 是一个特殊的 List,它用来管理跨进程的回调,特别是当回调对象是在不同进程中时。它在 AIDL(Android Interface Definition Language)通信中常常用来处理跨进程的通信。 Arr…...
ADC(二):外部触发
有关ADC的基础知识请参考标准库入门教程 ADC(二):外部触发 1、TIM1的CC1事件触发ADC1DMA重装载2、TIM3的TRGO事件(的更新事件)触发ADC1DMA重装载3、TIM3的TRGO事件(的捕获事件)触发ADC1DMA重装载4、优化TIM3的TRGO事件(的捕获事件)触发ADC1D…...
数仓开发那些事(8)
程序员圣经 为什么刚刚能运行,现在就不行 为什么刚刚不运行,现在就可以 为什么他的可以跑,我的不能跑 为什么我的可以跑,他的就不行 为什么这台电脑能,那台就不行 为什么这台电脑不行,那台就行 神州员工&a…...
【CSS in Depth 2 精译_096】16.4:CSS 中的三维变换 + 16.5:本章小结
当前内容所在位置(可进入专栏查看其他译好的章节内容) 第五部分 添加动效 ✔️【第 16 章 变换】 ✔️ 16.1 旋转、平移、缩放与倾斜 16.1.1 变换原点的更改16.1.2 多重变换的设置16.1.3 单个变换属性的设置 16.2 变换在动效中的应用 16.2.1 放大图标&am…...
【连续学习之ResCL算法】2020年AAAI会议论文:Residual continual learning
1 介绍 年份:2020 会议: AAAI Lee J, Joo D, Hong H G, et al. Residual continual learning[C]//Proceedings of the AAAI Conference on Artificial Intelligence. 2020, 34(04): 4553-4560. 本文提出的算法是Residual Continual Learning (ResC…...
后进先出(LIFO)详解
LIFO 是 Last In, First Out 的缩写,中文译为后进先出。这是一种数据结构的工作原则,类似于一摞盘子或一叠书本: 最后放进去的元素最先出来 -想象往筒状容器里放盘子: (1)你放进的最后一个盘子(…...
使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...
Oracle查询表空间大小
1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...
相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...
MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...
现代密码学 | 椭圆曲线密码学—附py代码
Elliptic Curve Cryptography 椭圆曲线密码学(ECC)是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础,例如椭圆曲线数字签…...
拉力测试cuda pytorch 把 4070显卡拉满
import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试,通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小,增大可提高计算复杂度duration: 测试持续时间(秒&…...
使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台
🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
使用Matplotlib创建炫酷的3D散点图:数据可视化的新维度
文章目录 基础实现代码代码解析进阶技巧1. 自定义点的大小和颜色2. 添加图例和样式美化3. 真实数据应用示例实用技巧与注意事项完整示例(带样式)应用场景在数据科学和可视化领域,三维图形能为我们提供更丰富的数据洞察。本文将手把手教你如何使用Python的Matplotlib库创建引…...
