spring项目中非spring管理类需通过工具类获取bean,核心是实现applicationcontextaware接口并用@component注册,封装getbean等方法支持类型安全获取;同时可扩展environment支持属性读取。

在 Spring 项目中,非 Spring 管理的类(比如普通工具类、静态方法、定时任务、Filter、Utils 类)无法直接使用 @Autowired 注入 Bean。此时需要手动从 Spring 容器中获取 Bean 实例——关键在于**拿到 ApplicationContext 或 BeanFactory 的引用**,再调用其 getBean() 方法。封装一个稳定、线程安全、支持多种获取方式的工具类是常见且推荐的做法。
核心原理:让 Spring 主动把上下文“塞进来”
Spring 在启动过程中会自动回调某些 Aware 接口。最常用的是 ApplicationContextAware,只要实现它并注册为 Spring Bean,Spring 就会在初始化时把 ApplicationContext 实例传入。
- 必须用
@Component(或@Service等)让该工具类被 Spring 扫描并管理 - 不能自己 new 工具类实例,否则回调不会触发,
applicationContext为空 - 静态字段保存
ApplicationContext是安全的,因为 Spring 上下文在整个应用生命周期内唯一且线程安全
标准工具类封装(推荐写法)
以下是一个生产环境常用的 SpringContextUtils 示例,支持按名称、类型、泛型、批量获取等多种方式:
- 使用
@Component自动注册,实现ApplicationContextAware - 加空值校验(
checkApplicationContext()),避免 NPE - 提供泛型方法,无需强制转型,类型更安全
- 支持获取所有某类型的 Bean(
getBeansOfType()),适合策略模式场景
示例代码片段:
@Component
public class SpringContextUtils implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext context) throws BeansException {
if (applicationContext == null) {
applicationContext = context;
}
}
private static void checkApplicationContext() {
if (applicationContext == null) {
throw new RuntimeException("applicationContext 未注入,请检查是否配置了 ApplicationContextAware");
}
}
public static <t> T getBean(Class<t> clazz) {
checkApplicationContext();
return applicationContext.getBean(clazz);
}
public static <t> T getBean(String name, Class<t> clazz) {
checkApplicationContext();
return applicationContext.getBean(name, clazz);
}
public static <t> Map<string t> getBeansOfType(Class<t> clazz) {
checkApplicationContext();
return applicationContext.getBeansOfType(clazz);
}
}</t></string></t></t></t></t></t>
获取当前运行环境配置(Environment)
除了 Bean,很多工具类还需读取 @Value 或 application.yml 中的属性。可在同一工具类中补充 Environment 支持:
- 通过
@Autowired注入Environment到工具类(需确保是 Spring 管理的 Bean) - 或直接从
applicationContext.getEnvironment()获取(更统一) - 建议封装
getProperty(String key, Class<t> type)</t>方法,带默认值和类型转换
例如:SpringContextUtils.getProperty("redis.timeout", Integer.class, 3000)
特殊场景补充说明
某些环境(如 WebFlux、Servlet 3.0+ 异步线程、单元测试)可能无法直接用 ApplicationContextAware,可考虑:
-
Web 环境下:用
ContextLoader.getCurrentWebApplicationContext()(仅限传统 Servlet 容器) -
非 Web 环境(如 Spring Boot CLI 或纯 Java 应用):确保主类用了
@SpringBootApplication,工具类能正常扫描到 - 避免循环依赖:工具类内部不要调用自身静态方法去获取另一个正在初始化中的 Bean
-
AOP 代理问题:若需获取被 AOP 增强的 Bean(如事务代理),应使用
getBean()返回的原始对象,而非自行 new 实例











