Spring Framework源码解析——ApplicationContextAware
版权声明
- 本文原创作者:谷哥的小弟
- 作者博客地址:http://blog.csdn.net/lfdfhl
一、概述
ApplicationContextAware
是 Spring 框架中用于让 Bean 能够感知并获取 ApplicationContext
容器实例的核心回调接口。通过实现该接口,Bean 可以在初始化阶段获得对整个 Spring 容器的引用,从而具备动态获取其他 Bean、发布事件、访问环境配置等高级能力。
该接口是 Spring Aware 系列接口(如 BeanNameAware
、BeanFactoryAware
、EnvironmentAware
等)的重要组成部分,体现了 Spring 容器“感知即服务”的设计哲学。
二、接口定义
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()
方法(入口)
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {// 1. 调用 Aware 接口方法(包括 ApplicationContextAware)invokeAwareMethods(beanName, bean);Object wrappedBean = bean;// 2. 执行 BeanPostProcessor 的 postProcessBeforeInitializationif (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);}// 3. 调用 InitializingBean.afterPropertiesSet() 和 init-methodinvokeInitMethods(beanName, wrappedBean, mbd);// 4. 执行 BeanPostProcessor 的 postProcessAfterInitializationif (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}return wrappedBean;
}
3.2 invokeAwareMethods()
方法源码
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()
源码如下:
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
初始化时,会显式设置:
// AbstractApplicationContext.refresh()
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {// ...beanFactory.setBeanClassLoader(getClassLoader());beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver());beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));// 关键:将当前 ApplicationContext 注入到 BeanFactorybeanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
}
关键点:
ApplicationContextAware
的注入实际由ApplicationContextAwareProcessor
完成,而非invokeAwareMethods()
!
五、ApplicationContextAwareProcessor
:真正的实现者
Spring 并未直接在 invokeAwareMethods()
中处理 ApplicationContextAware
,而是通过 BeanPostProcessor
机制实现,以支持更灵活的控制(如忽略某些 Aware 接口)。
5.1 ApplicationContextAwareProcessor
构造
public class ApplicationContextAwareProcessor implements BeanPostProcessor {private final ApplicationContext applicationContext;public ApplicationContextAwareProcessor(ApplicationContext applicationContext) {this.applicationContext = applicationContext;}@Overridepublic 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(避免循环依赖)
@Component
public class DynamicBeanService implements ApplicationContextAware {private ApplicationContext applicationContext;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) {this.applicationContext = applicationContext;}public void process(String beanName) {// 动态获取 Bean,避免构造器或字段注入导致的循环依赖MyService service = applicationContext.getBean(beanName, MyService.class);service.execute();}
}
7.2 发布应用事件
@Component
public class EventPublisher implements ApplicationContextAware {private ApplicationEventPublisher eventPublisher;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) {this.eventPublisher = applicationContext;}public void triggerEvent() {eventPublisher.publishEvent(new CustomEvent("data"));}
}
7.3 访问环境配置
@Component
public class ConfigReader implements ApplicationContextAware {private Environment environment;@Overridepublic 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 编程风格。
@Service
public class MyService {@Autowiredprivate 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 容器的扩展能力与设计哲学。