ApplicationContextAware用于在非Spring管理对象或静态上下文中动态获取Bean,适用于工具类、new创建对象、条件查找Bean及自定义工厂等场景,需确保类被Spring托管且避免循环依赖与静态覆盖问题。

在 Spring 中,可以通过实现 ApplicationContextAware 接口,让 Bean 在初始化时自动获得 ApplicationContext 容器引用,从而在运行时获取其他 Bean、发布事件、获取环境配置等。
为什么用 ApplicationContextAware 而不是直接注入?
ApplicationContextAware 适用于以下场景:
- 普通工具类、静态方法中需要动态获取 Bean(Spring 不允许直接 @Autowired 静态字段)
- Bean 尚未被 Spring 管理(如通过 new 创建的对象),但需要临时访问容器
- 需要在初始化后根据条件从容器中查找特定 Bean(比如按名称、类型、注解筛选)
- 自定义工厂、代理或 AOP 增强逻辑中需主动操作上下文
基本使用步骤
只需三步即可启用:
- 让目标类实现 ApplicationContextAware 接口
- 重写 setApplicationContext(ApplicationContext ctx) 方法,保存上下文引用(建议用 static 字段或成员变量)
- 确保该类是 Spring 管理的 Bean(加 @Component、@Service 或 XML 配置)
示例代码:
@Component
public class ContextHolder implements ApplicationContextAware {
private static ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
context = applicationContext;
}
public static <T> T getBean(Class<T> clazz) {
return context.getBean(clazz);
}
public static Object getBean(String name) {
return context.getBean(name);
}
}
注意事项和常见问题
使用时需注意几个关键点:
- 必须是 Spring 托管 Bean:非 @Component 类即使实现了接口也不会被回调,setApplicationContext 不会执行
- 避免循环依赖:如果在 setApplicationContext 中立即调用 getBean 获取当前类自身或其他正在创建中的 Bean,可能触发循环依赖异常
- 线程安全:ApplicationContext 是线程安全的,但你自己保存的 context 引用如果是 static 的,也要确保初始化完成后再被多线程使用(Spring 容器启动完成后才调用 setApplicationContext,一般没问题)
- 替代方案更推荐:Spring 5.3+ 推荐使用 ObjectProvider 或构造器注入 ApplicationContext;若只是取某个固定 Bean,优先用 @Autowired 更清晰可控
不推荐的误用方式
以下做法容易出问题,应避免:
- 在工具类里 new 出实现 ApplicationContextAware 的对象——不会触发回调
- 把 ApplicationContext 存到 ThreadLocal 里手动传递——破坏 Spring 生命周期管理,且易内存泄漏
- 在 setApplicationContext 里执行耗时或阻塞操作(如远程调用、文件读写)——会拖慢容器启动
- 多个类都用 static 方式保存 context,导致覆盖或空指针(尤其在多上下文环境如 Spring Boot 多个 ApplicationContext 时)
















