如何在在非 Spring 管理的类中访问 Spring Bean
org.springframework.context.ApplicationContextAware
是 Spring 框架中的一个接口,它的主要作用是让一个 Bean 可以获得 Spring 容器(即 ApplicationContext
)的引用,从而能以编程方式访问容器中的其他 Bean、资源等。
🌟 1. 接口定义与继承关系
- 所在包:
org.springframework.context
- 继承自:
org.springframework.beans.factory.Aware
- 核心方法:
setApplicationContext(ApplicationContext applicationContext)
- 容器在创建实现了此接口的 Bean 后自动调用,传入当前的
ApplicationContext
。
- 容器在创建实现了此接口的 Bean 后自动调用,传入当前的
public interface ApplicationContextAware {
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
setApplicationContext
方法:当 Spring 容器创建这个 Bean 实例时,如果它实现了ApplicationContextAware
接口,Spring 会自动调用这个方法,并将ApplicationContext
作为参数传入。ApplicationContext
:是 Spring 的核心接口之一,代表了整个 IoC 容器,提供了大量方法来获取 Bean、资源文件、发布事件等。
🚗 2. 工作原理
- 识别阶段
Spring 在启动并扫描 Bean 定义时,会检测哪些 Bean 实现了ApplicationContextAware
接口。 - 实例化与依赖注入
容器实例化 Bean 并完成一般的依赖注入后,调用Aware
接口族的回调方法(含setApplicationContext
)。 - 回调执行
实现类接收到ApplicationContext
,可将其保存为静态变量或实例变量,以便后续编程式调用。
🧠 3. 使用场景
- 需要。
- 编写工具类或者框架组件,需要访问容器中的其他 Bean。
- 某些第三方集成(例如自定义注解处理器)中需要使用 Spring 容器功能。
📦 4. 示例代码
1️⃣ 自定义一个 Bean 实现 ApplicationContextAware
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.Environment;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import java.util.Map;
/**
* Spring 应用上下文工具类
* <p>实现 ApplicationContextAware 接口用于获取 Spring 应用上下文,
* 提供静态方法方便在非 Spring 管理环境中获取 Bean 及环境信息等</p>
*/
public class SpringContextUtils implements ApplicationContextAware {
// 静态保存 Spring 应用上下文
private static ConfigurableApplicationContext applicationContext;
/**
* Spring 容器自动回调方法,注入应用上下文
* @param ctx Spring 应用上下文对象
* @throws BeansException 当上下文注入失败时抛出异常
*/
@Override
public void setApplicationContext(@NonNull ApplicationContext ctx) throws BeansException {
SpringContextUtils.applicationContext = (ConfigurableApplicationContext) ctx;
}
/**
* 获取当前 Spring 应用上下文
* @return 返回当前应用上下文实例
*/
public static ApplicationContext getApplicationContext() {
return applicationContext;
}
/**
* 根据 Bean 名称获取 Spring 容器中的 Bean 实例
* @param name Bean 在容器中注册的名称
* @return 返回匹配的 Bean 实例
* @throws BeansException 当找不到对应 Bean 时抛出异常
*/
public static Object getBean(String name) throws BeansException {
return applicationContext.getBean(name);
}
/**
* 根据类型获取 Spring 容器中的 Bean 实例
* @param requiredType Bean 的类类型
* @param <T> 泛型类型参数
* @return 返回匹配类型的 Bean 实例
* @throws BeansException 当找不到唯一匹配的 Bean 时抛出异常
*/
public static <T> T getBean(Class<T> requiredType) throws BeansException {
return applicationContext.getBean(requiredType);
}
/**
* 根据名称和类型获取 Bean,支持强制类型转换
* @param name Bean 名称
* @param requiredType Bean 类型
* @param <T> 泛型类型参数
* @return 转换后的 Bean 实例
*/
public static <T> T getBean(String name, Class<T> requiredType) {
return applicationContext.getBean(name, requiredType);
}
/**
* 根据类型获取容器中所有匹配的 Bean 实例
* @param type Bean 类型
* @param <T> 泛型类型
* @return 返回 Bean 名称到 Bean 实例的映射
*/
public static <T> Map<String, T> getBeansOfType(Class<T> type) {
return applicationContext.getBeansOfType(type);
}
/**
* 判断容器中是否包含指定名称的 Bean
* @param name Bean 名称
* @return 存在则返回 true,否则 false
*/
public static boolean containsBean(String name) {
return applicationContext.containsBean(name);
}
/**
* 判断指定名称的 Bean 是否为单例
* @param name Bean 名称
* @return 是单例返回 true,否则 false
*/
public static boolean isSingleton(String name) {
return applicationContext.isSingleton(name);
}
/**
* 获取指定 Bean 的类型
* @param name Bean 名称
* @return Bean 的类型
*/
public static Class<?> getType(String name) {
return applicationContext.getType(name);
}
/**
* 获取 Bean 的别名
* @param name Bean 名称
* @return 别名数组
*/
public static String[] getAliases(String name) {
return applicationContext.getAliases(name);
}
/**
* 发布 Spring 事件
* @param event 事件对象
*/
public static void publishEvent(Object event) {
applicationContext.publishEvent(event);
}
/**
* 获取 Environment 对象,可获取配置属性等信息
* @return Environment 实例
*/
public static Environment getEnvironment() {
return applicationContext.getEnvironment();
}
/**
* 根据属性名获取配置值
* @param key 属性名
* @return 属性值,若不存在则返回 null
*/
public static String getProperty(String key) {
return applicationContext.getEnvironment().getProperty(key);
}
/**
* 注册 JVM 关闭钩子,确保 Spring 容器正常关闭
*/
public static void registerShutdownHook() {
applicationContext.registerShutdownHook();
}
/**
* 获取当前激活的 Spring Profile 列表
* @return 激活的 Profile 数组
*/
public static String[] getActiveProfiles() {
return applicationContext.getEnvironment().getActiveProfiles();
}
}
2️⃣ 使用它来获取 Spring 管理的 Bean:
AppUnitTypesService appUnitTypesService = SpringContextUtils.getBean(AppUnitTypesService.class);
List<AppUnitTypes> productTypes = appUnitTypesService.list();
🔍 5. 注意事项
注意点 | 说明 |
---|---|
不推荐滥用 | 频繁通过 ApplicationContextAware 获取 Bean 会破坏 Spring 的依赖注入原则(DI),降低代码的可测试性和解耦性。 |
线程安全 | ApplicationContext 本身是线程安全的,但你获取到的 Bean 可能不是(取决于其作用域)。 |
替代方式 | 更推荐使用构造器注入或字段注入来获取依赖。只有在无法通过 DI 注入的场景中再使用它。 |
✅ 5. 总结
特性 | 描述 |
---|---|
所属接口 | org.springframework.context.ApplicationContextAware |
作用 | 获取 Spring 容器对象(ApplicationContext ) |
方法 | setApplicationContext(ApplicationContext applicationContext) |
用途 | 在 Bean 中动态访问 Spring 管理的对象 |
推荐使用 | 工具类、集成框架、必须访问容器的特殊场景 |
如果你有具体的使用场景或代码示例,我可以帮你分析是否该使用它,或者有没有更优雅的替代方案。