版权声明
- 本文原创作者:谷哥的小弟
- 作者博客地址:http://blog.csdn.net/lfdfhl

一、概述
ApplicationContextAware
是 Spring 框架中用于让 Bean 能够感知并获取 ApplicationContext
容器实例的核心回调接口。通过实现该接口,Bean 可以在初始化阶段获得对整个 Spring 容器的引用,从而具备动态获取其他 Bean、发布事件、访问环境配置等高级能力。
该接口是 Spring Aware 系列接口 (如 BeanNameAware
、BeanFactoryAware
、EnvironmentAware
等)的重要组成部分,体现了 Spring 容器"感知即服务"的设计哲学。
二、接口定义
java
public interface ApplicationContextAware extends Aware {
/**
* 在 Bean 初始化早期阶段由容器调用
* 注入当前的 ApplicationContext 实例
* @param applicationContext 当前使用的 ApplicationContext
* @throws BeansException 如果设置失败
*/
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
关键特征如下:
- 继承自
Aware
标记接口:表明该接口用于"感知"容器能力; - 回调方法
setApplicationContext()
:由容器自动调用,注入ApplicationContext
; - 执行时机早 :在
BeanPostProcessor.postProcessBeforeInitialization()
之前; - 适用于需要容器上下文的场景:如动态 Bean 获取、事件发布、环境访问等。
三、核心执行流程分析
ApplicationContextAware
的调用发生在 Bean 初始化的早期阶段,具体由 AbstractAutowireCapableBeanFactory.invokeAwareMethods()
方法处理。
3.1 initializeBean()
方法(入口)
java
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
// 1. 调用 Aware 接口方法(包括 ApplicationContextAware)
invokeAwareMethods(beanName, bean);
Object wrappedBean = bean;
// 2. 执行 BeanPostProcessor 的 postProcessBeforeInitialization
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
// 3. 调用 InitializingBean.afterPropertiesSet() 和 init-method
invokeInitMethods(beanName, wrappedBean, mbd);
// 4. 执行 BeanPostProcessor 的 postProcessAfterInitialization
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
3.2 invokeAwareMethods()
方法源码
java
private void invokeAwareMethods(String beanName, Object bean) {
if (bean instanceof Aware) {
if (bean instanceof BeanNameAware) {
((BeanNameAware) bean).setBeanName(beanName);
}
if (bean instanceof BeanClassLoaderAware) {
ClassLoader bcl = getBeanClassLoader();
if (bcl != null) {
((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
}
}
if (bean instanceof BeanFactoryAware) {
((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
}
if (bean instanceof ApplicationContextAware) {
// 获取当前的 ApplicationContext 并注入
ApplicationContext applicationContext = getApplicationContext();
((ApplicationContextAware) bean).setApplicationContext(applicationContext);
}
}
}
代码解析:
- 类型检查 :通过
instanceof
判断 Bean 是否实现了特定Aware
接口; - 注入顺序 :
BeanNameAware
→BeanClassLoaderAware
→BeanFactoryAware
→ApplicationContextAware
; getApplicationContext()
:从当前BeanFactory
向上转型获取ApplicationContext
(前提是当前BeanFactory
是ApplicationContext
的子容器)。
注意 :若
BeanFactory
不是ApplicationContext
(如直接使用DefaultListableBeanFactory
),则getApplicationContext()
会抛出IllegalStateException
。
四、getApplicationContext()
的实现机制
AbstractAutowireCapableBeanFactory
本身并不持有 ApplicationContext
,而是通过委托机制获取。
getApplicationContext()
源码如下:
java
protected ApplicationContext getApplicationContext() {
if (this.applicationContext == null) {
// 尝试从父 BeanFactory 获取
if (this.parentBeanFactory instanceof AbstractAutowireCapableBeanFactory) {
return ((AbstractAutowireCapableBeanFactory) this.parentBeanFactory).getApplicationContext();
}
throw new IllegalStateException("ApplicationContext not set on BeanFactory");
}
return this.applicationContext;
}
但在 AbstractApplicationContext
初始化时,会显式设置:
java
// AbstractApplicationContext.refresh()
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// ...
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver());
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));
// 关键:将当前 ApplicationContext 注入到 BeanFactory
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
}
关键点 :
ApplicationContextAware
的注入实际由ApplicationContextAwareProcessor
完成,而非invokeAwareMethods()
!
五、ApplicationContextAwareProcessor
:真正的实现者
Spring 并未直接在 invokeAwareMethods()
中处理 ApplicationContextAware
,而是通过 BeanPostProcessor
机制实现,以支持更灵活的控制(如忽略某些 Aware 接口)。
5.1 ApplicationContextAwareProcessor
构造
java
public class ApplicationContextAwareProcessor implements BeanPostProcessor {
private final ApplicationContext applicationContext;
public ApplicationContextAwareProcessor(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (!(bean instanceof EnvironmentAware ||
bean instanceof EmbeddedValueResolverAware ||
bean instanceof ResourceLoaderAware ||
bean instanceof ApplicationEventPublisherAware ||
bean instanceof MessageSourceAware ||
bean instanceof ApplicationContextAware)) {
return bean;
}
// 设置访问控制上下文(略)
if (bean instanceof EnvironmentAware) {
((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
}
if (bean instanceof EmbeddedValueResolverAware) {
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(
new EmbeddedValueResolver(this.applicationContext.getBeanFactory(), this.applicationContext.getEnvironment()));
}
if (bean instanceof ResourceLoaderAware) {
((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
}
if (bean instanceof ApplicationEventPublisherAware) {
((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
}
if (bean instanceof MessageSourceAware) {
((MessageSourceAware) bean).setMessageSource(this.applicationContext);
}
if (bean instanceof ApplicationContextAware) {
invokeAwareInterfaces(bean);
}
return bean;
}
private void invokeAwareInterfaces(Object bean) {
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
}
}
}
5.2 为什么使用 BeanPostProcessor
?
- 统一管理 :将多个
Aware
接口的注入逻辑集中处理; - 可配置性 :可通过
ignoreDependencyInterface()
忽略某些接口(如测试时); - 执行时机更合理:在属性注入后、初始化前执行,确保容器已完全可用;
- 避免硬编码 :解耦
BeanFactory
与ApplicationContext
的直接依赖。
六、执行顺序与生命周期位置
ApplicationContextAware.setApplicationContext()
的执行顺序如下:
- Bean 实例化(
createBeanInstance
) - 属性注入(
populateBean
) ApplicationContextAwareProcessor.postProcessBeforeInitialization
(注入ApplicationContext
)@PostConstruct
方法InitializingBean.afterPropertiesSet()
init-method
关键结论 :
ApplicationContextAware
的回调发生在属性注入之后、初始化方法之前,此时容器已完全可用。
七、典型应用场景
7.1 动态获取 Bean(避免循环依赖)
java
@Component
public class DynamicBeanService implements ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
public void process(String beanName) {
// 动态获取 Bean,避免构造器或字段注入导致的循环依赖
MyService service = applicationContext.getBean(beanName, MyService.class);
service.execute();
}
}
7.2 发布应用事件
java
@Component
public class EventPublisher implements ApplicationContextAware {
private ApplicationEventPublisher eventPublisher;
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
this.eventPublisher = applicationContext;
}
public void triggerEvent() {
eventPublisher.publishEvent(new CustomEvent("data"));
}
}
7.3 访问环境配置
java
@Component
public class ConfigReader implements ApplicationContextAware {
private Environment environment;
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
this.environment = applicationContext.getEnvironment();
}
public String getProperty(String key) {
return environment.getProperty(key);
}
}
八、与 @Autowired ApplicationContext
的对比
方式 | 类型 | 是否依赖 Spring API | 执行时机 | 推荐度 |
---|---|---|---|---|
ApplicationContextAware |
接口回调 | 是 | 属性注入后、初始化前 | ⭐⭐ |
@Autowired ApplicationContext |
依赖注入 | 是(但更简洁) | 属性注入阶段 | ⭐⭐⭐⭐ |
推荐使用
@Autowired ApplicationContext
,原因:
- 代码更简洁;
- 无需实现接口;
- 同样安全可靠;
- 符合现代 Spring 编程风格。
java
@Service
public class MyService {
@Autowired
private ApplicationContext applicationContext;
}
九、最佳实践与注意事项
9.1 注意事项
- 避免滥用 :不应将
ApplicationContext
作为全局变量随意传递; - 线程安全 :
ApplicationContext
本身是线程安全的,但获取的 Bean 可能不是; - 作用域限制:在原型(Prototype)Bean 中使用需谨慎,确保引用有效;
- 测试友好性 :实现
ApplicationContextAware
会增加单元测试复杂度。
9.2 替代方案建议
- 优先使用
@Autowired ApplicationContext
; - 如需发布事件,可直接注入
ApplicationEventPublisher
; - 如需环境配置,注入
Environment
; - 如需资源加载,注入
ResourceLoader
。
十、源码设计思想总结
ApplicationContextAware
的设计体现了 Spring 的以下核心思想:
- 控制反转(IoC)的补充:在必要时允许 Bean "主动"获取容器能力;
- 关注点分离 :通过
Aware
接口明确表达依赖意图; - 可扩展性 :通过
BeanPostProcessor
机制实现灵活注入; - 生命周期管理:在合适的时机注入容器引用,确保可用性;
- 向后兼容:保留接口方式以支持传统应用,同时推荐更现代的注入方式。
ApplicationContextAware
是 Spring 框架中用于让 Bean 获取容器上下文引用的重要接口。其核心逻辑由 ApplicationContextAwareProcessor
通过 BeanPostProcessor
机制实现,在 Bean 属性注入后、初始化前完成回调。
尽管功能强大,但出于代码简洁性和解耦考虑,推荐优先使用 @Autowired ApplicationContext
。理解 ApplicationContextAware
的执行机制、生命周期位置及与 Aware
系列接口的关系,有助于深入掌握 Spring 容器的扩展能力与设计哲学。