当前位置: 首页 > news >正文

Java 实现SpringContextUtils工具类,手动获取Bean

SpringContextUtils 工具类实现

下面是一个完整的 Spring 上下文工具类实现,用于从 Spring 容器中获取 Bean。这个工具类考虑了线程安全、性能优化和易用性,并提供了多种获取 Bean 的方式。

完整实现代码

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;import java.util.Map;/*** Spring 上下文工具类,用于获取容器中的Bean* * 功能包括:* 1. 获取ApplicationContext* 2. 通过名称获取Bean* 3. 通过类型获取Bean* 4. 通过名称和类型获取Bean* 5. 获取指定类型的所有Bean* 6. 获取当前环境配置*/
@Component
public class SpringContextUtils implements ApplicationContextAware {/*** 静态ApplicationContext*/private static ApplicationContext applicationContext;/*** 设置ApplicationContext*/@Overridepublic void setApplicationContext(@Nullable ApplicationContext applicationContext) throws BeansException {if (SpringContextUtils.applicationContext == null) {SpringContextUtils.applicationContext = applicationContext;}}/*** 获取ApplicationContext*/public static ApplicationContext getApplicationContext() {checkApplicationContext();return applicationContext;}/*** 通过名称获取Bean* @param name Bean名称* @return Bean实例*/@SuppressWarnings("unchecked")public static <T> T getBean(String name) {checkApplicationContext();return (T) applicationContext.getBean(name);}/*** 通过类型获取Bean* @param clazz Bean类型* @return Bean实例*/public static <T> T getBean(Class<T> clazz) {checkApplicationContext();return applicationContext.getBean(clazz);}/*** 通过名称和类型获取Bean* @param name Bean名称* @param clazz Bean类型* @return Bean实例*/public static <T> T getBean(String name, Class<T> clazz) {checkApplicationContext();return applicationContext.getBean(name, clazz);}/*** 获取指定类型的所有Bean* @param clazz Bean类型* @return Bean名称与实例的映射*/public static <T> Map<String, T> getBeansOfType(Class<T> clazz) {checkApplicationContext();return applicationContext.getBeansOfType(clazz);}/*** 获取当前环境配置* @param key 配置键* @return 配置值*/public static String getProperty(String key) {checkApplicationContext();return applicationContext.getEnvironment().getProperty(key);}/*** 检查ApplicationContext是否已注入*/private static void checkApplicationContext() {if (applicationContext == null) {throw new IllegalStateException("ApplicationContext未注入,请在Spring配置中定义SpringContextUtils");}}
}

功能说明

1. 核心功能

  • 获取 ApplicationContextgetApplicationContext()
  • 通过名称获取 BeangetBean(String name)
  • 通过类型获取 BeangetBean(Class<T> clazz)
  • 通过名称和类型获取 BeangetBean(String name, Class<T> clazz)
  • 获取指定类型的所有 BeangetBeansOfType(Class<T> clazz)
  • 获取环境配置getProperty(String key)

2. 线程安全性

  • 使用静态变量存储 ApplicationContext,保证全局唯一
  • 通过 @Component 注解让 Spring 管理工具类实例
  • 实现 ApplicationContextAware 接口自动注入上下文

3. 异常处理

  • 检查 ApplicationContext 是否已注入,未注入时抛出明确异常
  • 使用 @Nullable 注解标记可为空的参数
  • 添加泛型支持,减少类型转换

使用示例

1. 基本使用

// 获取ApplicationContext
ApplicationContext context = SpringContextUtils.getApplicationContext();// 通过名称获取Bean
UserService userService = SpringContextUtils.getBean("userService");// 通过类型获取Bean
UserService userService = SpringContextUtils.getBean(UserService.class);// 通过名称和类型获取Bean
UserService userService = SpringContextUtils.getBean("userService", UserService.class);

2. 获取所有同类型Bean

// 获取所有实现UserService接口的Bean
Map<String, UserService> userServices = SpringContextUtils.getBeansOfType(UserService.class);userServices.forEach((name, service) -> {System.out.println("Bean名称: " + name + ", 实例: " + service);
});

3. 获取环境配置

// 获取application.properties/yml中的配置
String appName = SpringContextUtils.getProperty("spring.application.name");
String serverPort = SpringContextUtils.getProperty("server.port");

高级用法

1. 在非Spring管理的类中使用

public class NonSpringClass {public void someMethod() {// 获取Spring容器中的BeanUserRepository repository = SpringContextUtils.getBean(UserRepository.class);repository.save(new User());}
}

2. 在静态方法中使用

public class UtilityClass {public static void doSomething() {// 静态方法中获取BeanEmailService emailService = SpringContextUtils.getBean(EmailService.class);emailService.send("test@example.com", "Hello");}
}

3. 在JUnit测试中使用

@SpringBootTest
public class UserServiceTest {@Testpublic void testGetUser() {// 在测试中获取BeanUserService userService = SpringContextUtils.getBean(UserService.class);User user = userService.getUserById(1L);assertNotNull(user);}
}

实现原理

  1. ApplicationContextAware 接口

    • Spring 会在初始化时自动调用 setApplicationContext 方法
    • 将 ApplicationContext 注入到工具类的静态变量中
  2. 静态方法访问

    • 所有方法都是静态的,方便在任何地方调用
    • 内部检查 ApplicationContext 是否已初始化
  3. 泛型支持

    • 减少显式类型转换,提高代码安全性
    • 编译器会检查类型是否匹配

注意事项

  1. 初始化时机

    • 确保 Spring 容器完全初始化后再使用工具类
    • 不要在 Bean 的构造方法中使用,因为此时 Bean 还未完全初始化
  2. 单元测试

    • 在测试中需要先启动 Spring 上下文
    • 可以使用 @SpringBootTest 注解
  3. 多线程安全

    • ApplicationContext 是线程安全的
    • 工具类本身不包含可变状态,也是线程安全的
  4. 替代方案

    • 在 Spring Boot 中可以直接使用依赖注入
    • 这个工具类主要用在无法使用依赖注入的场景

扩展功能

如果需要更多功能,可以扩展以下方法:

/*** 获取当前环境profile*/
public static String[] getActiveProfiles() {checkApplicationContext();return applicationContext.getEnvironment().getActiveProfiles();
}/*** 判断当前是否是指定环境*/
public static boolean isProfileActive(String profile) {checkApplicationContext();String[] activeProfiles = getActiveProfiles();return Arrays.asList(activeProfiles).contains(profile);
}/*** 发布事件*/
public static void publishEvent(Object event) {checkApplicationContext();applicationContext.publishEvent(event);
}

这个 SpringContextUtils 工具类提供了一种简洁的方式来访问 Spring 容器中的 Bean,特别适合在非 Spring 管理的类中获取 Spring Bean 的场景。

相关文章:

  • 鸿蒙NEXT开发网络相关工具类(ArkTs)
  • node.js 实战——(概念以及Buffer 知识点学习)
  • 数据结构线性表的顺序存储结构
  • openEuler安装nvidia驱动【详细版】
  • 外贸获客新革命:基于AI的搜索引擎排名攻防战——48小时抢占谷歌TOP3的技术逻辑与实战路径
  • 基于VUE+Node.JS实现(Web)学生组队网站
  • LInux平均负载
  • maven中pom.xml setting.xml关系
  • 二叉树OJ题目
  • 大模型框架技术全景与下一代架构演进
  • 如何批量为多张图片(JPG、PNG、BMP、WEBP 等格式)添加自定义水印保护
  • C++ 容器查找效率
  • 20250423修改和查看荣品的PRO-RK3566开发板的buildroot linux系统的cpu频率
  • Linux命令-sar
  • Python内置函数---bytearray()
  • 【Java设计模式及实践学习-第4章节-结构型模式】
  • 一对多的数据结构(树)的基本概念
  • spring-session-data-redis使用
  • 困局与破局:当传统校园能源管理遭遇“散沙式“能耗困局
  • opencv--图像滤波
  • 夜读丨一条鱼的使命
  • 央行副行长陆磊:国际化程度有效提升是上海国际金融中心建设的一个主要方向
  • 重庆一幼儿园回应招聘硕士幼教:统一标准,江北区学前教育岗的硬性要求
  • “未来3天公布”,特朗普俄乌“和平计划”是什么?普京泽连斯基什么态度?
  • 导演汪俊:与孙俪默契合作,还原“蛮好的人生”
  • 5旬辅警30余年前被人顶替上中专?河南沁阳:基本属实,将依法处理