不推荐手动通过 applicationcontext 获取 bean,因其违背 ioc 原则;特殊场景下应通过 applicationcontextaware 或 @autowired 安全注入,并优先使用 ctx.getbean(myservice.class) 按类型获取。

在依赖注入场景中,不推荐用 ApplicationContext 手动获取 Bean——因为这违背了 Spring 的 IoC 设计初衷。但某些特殊情况下(如工具类、静态方法、非 Spring 管理对象、初始化早期阶段),确实需要绕过自动注入,转而手动从容器取 Bean。关键不是“能不能”,而是“怎么安全、合规地做”。
为什么不能在 @Autowired 字段上直接用 ApplicationContext?
ApplicationContext 本身就是一个 Bean,可以被注入,但它不能用于初始化自身或解决循环依赖。常见误区是:在某个类里声明 @Autowired ApplicationContext ctx,然后在构造器或 @PostConstruct 里立刻调用 ctx.getBean(...)——这看似可行,但若目标 Bean 尚未完成创建(比如依赖顺序未就绪),就会抛出 NoSuchBeanDefinitionException 或返回 null。
推荐做法:用 ApplicationContextAware 或 @Autowired 注入方式
确保工具类本身由 Spring 管理,并在上下文完全就绪后才使用:
- 实现
ApplicationContextAware接口(最经典、线程安全、启动即生效) - 用
@Component + @Autowired注入 ApplicationContext(简洁,但要求该类必须是 Spring Bean) - 避免在静态代码块、static 工具方法内部直接 new 对象后调用 getBean(此时 ApplicationContext 还没初始化)
获取 Bean 的三种常用 getBean 调用形式
拿到 ApplicationContext 后,优先按类型获取,减少硬编码名称:
-
ctx.getBean(MyService.class)—— 最安全,类型检查强,推荐 -
ctx.getBean("myService", MyService.class)—— 指定名称+类型,适合多实现类场景(如不同 profile 下的实现) -
ctx.getBean("myService")—— 返回 Object,需强制转型,易出ClassCastException,不建议
注意生命周期与线程安全
ApplicationContext 是单例、线程安全的,可全局缓存复用。但要注意:
- 不要在 @PostConstruct 中获取 prototype 类型 Bean 并长期持有——它不会自动刷新
- 如果要获取 prototype Bean,每次都要调用
getBean(),不能缓存实例 - 在异步线程(如
@Async方法)中使用时,确保 ApplicationContext 仍存活(Spring Boot 默认支持)











