在 Spring Boot 中手动获取 Bean 需先获取 ApplicationContext,推荐实现 ApplicationContextAware 接口缓存上下文并提供静态 getBean 方法;支持按类型、名称或名称+类型三种方式获取;适用于工具类、Filter、非 Spring 管理对象等 @Autowired 失效场景。

在 Spring Boot 中手动获取容器中的 Bean,核心前提是先拿到 ApplicationContext(Spring 应用上下文),再通过它调用 getBean() 方法。这不是常规写法,但确实必要——比如工具类、静态方法、Filter、Interceptor 或非 Spring 管理的对象里,@Autowired 失效时就得靠它。
怎么拿到 ApplicationContext
最稳妥、推荐的方式是实现 ApplicationContextAware 接口,让 Spring 主动把上下文注入进来:
- 写一个工具类(如
SpringUtil),加上@Component注解确保被扫描 - 实现
ApplicationContextAware,重写setApplicationContext方法,把传入的上下文缓存为静态变量 - 提供一个静态方法(如
getBean(Class<T>))供外部直接调用
注意:不能在静态代码块或构造器中提前使用该上下文,必须等 Spring 完成初始化后再调用。
三种常用 getBean 调用方式
拿到 ApplicationContext 后,可按需选择以下任一方式获取 Bean:
-
按类型获取:
context.getBean(YourService.class)—— 最安全,推荐用于单类型唯一 Bean -
按名称获取:
context.getBean("yourService")—— 名称默认是类名首字母小写,适合有多个同类型 Bean 时指定 -
按名称 + 类型获取:
context.getBean("yourService", YourService.class)—— 兼顾类型安全与名称控制,避免强转异常
哪些场景必须手动获取
依赖注入(@Autowired / 构造器注入)覆盖不了的地方,就得手动捞:
- 工具类里的静态方法(如
DateUtils.formatNow()内部要调用MessageSource) - 自定义 Filter、Servlet、WebSocketHandler 等底层组件,它们不是 Spring Bean
- 定时任务中用
new创建的对象,未被 Spring 管理 - 第三方 SDK 回调函数里需要访问业务 Service
不建议的做法和风险
有些写法看似能用,但隐患明显:
- 在
@SpringBootApplication的main方法里把上下文赋给静态变量 —— 启动未完成时可能为空,且测试环境容易出问题 - 每次需要都 new 一个
ClassPathXmlApplicationContext—— 会重复加载容器,内存泄漏、配置冲突 - 在非 Spring Bean 类里直接
@Autowired ApplicationContext—— 注入失败,字段为 null
手动取 Bean 是补漏手段,不是设计首选。优先用构造器注入,清晰、可控、易测。


















