当前位置: 首页 > news >正文

Spring Framework源码解析——ApplicationContextAware


版权声明

  • 本文原创作者:谷哥的小弟
  • 作者博客地址:http://blog.csdn.net/lfdfhl

在这里插入图片描述

一、概述

ApplicationContextAware 是 Spring 框架中用于让 Bean 能够感知并获取 ApplicationContext 容器实例的核心回调接口。通过实现该接口,Bean 可以在初始化阶段获得对整个 Spring 容器的引用,从而具备动态获取其他 Bean、发布事件、访问环境配置等高级能力。

该接口是 Spring Aware 系列接口(如 BeanNameAwareBeanFactoryAwareEnvironmentAware 等)的重要组成部分,体现了 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 接口;
  • 注入顺序BeanNameAwareBeanClassLoaderAwareBeanFactoryAwareApplicationContextAware
  • getApplicationContext():从当前 BeanFactory 向上转型获取 ApplicationContext(前提是当前 BeanFactoryApplicationContext 的子容器)。

注意:若 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

  1. 统一管理:将多个 Aware 接口的注入逻辑集中处理;
  2. 可配置性:可通过 ignoreDependencyInterface() 忽略某些接口(如测试时);
  3. 执行时机更合理:在属性注入后、初始化前执行,确保容器已完全可用;
  4. 避免硬编码:解耦 BeanFactoryApplicationContext 的直接依赖。

六、执行顺序与生命周期位置

ApplicationContextAware.setApplicationContext() 的执行顺序如下:

  1. Bean 实例化(createBeanInstance
  2. 属性注入(populateBean
  3. ApplicationContextAwareProcessor.postProcessBeforeInitialization(注入 ApplicationContext
  4. @PostConstruct 方法
  5. InitializingBean.afterPropertiesSet()
  6. 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 的以下核心思想:

  1. 控制反转(IoC)的补充:在必要时允许 Bean “主动”获取容器能力;
  2. 关注点分离:通过 Aware 接口明确表达依赖意图;
  3. 可扩展性:通过 BeanPostProcessor 机制实现灵活注入;
  4. 生命周期管理:在合适的时机注入容器引用,确保可用性;
  5. 向后兼容:保留接口方式以支持传统应用,同时推荐更现代的注入方式。

ApplicationContextAware 是 Spring 框架中用于让 Bean 获取容器上下文引用的重要接口。其核心逻辑由 ApplicationContextAwareProcessor 通过 BeanPostProcessor 机制实现,在 Bean 属性注入后、初始化前完成回调。

尽管功能强大,但出于代码简洁性和解耦考虑,推荐优先使用 @Autowired ApplicationContext。理解 ApplicationContextAware 的执行机制、生命周期位置及与 Aware 系列接口的关系,有助于深入掌握 Spring 容器的扩展能力与设计哲学。

http://www.dtcms.com/a/453572.html

相关文章:

  • 30个做设计的网站wordpress远程图片下载
  • 建网站权威机构西安专业网站建设服务
  • Express+Vue表格数据分页联调:模拟数据与真实接口的无缝切换
  • Qt 多线程与并发编程详解
  • 第五个实验——动态nat地址转换操作
  • 排查 TCP 连接中 TIME_WAIT 状态异常
  • 《C++ 实际应用系列》第二部分:内存管理与性能优化实战
  • 登建设厅锁子的是哪个网站祥云平台网站管理系统
  • 浙江省建设厅网站在哪里手机网站制作招聘
  • nat server 概念及题目
  • 试看30秒做受小视频网站深圳外贸网站制作
  • 网站营销推广怎么做网络营销推广网站建设关于公司怎么写
  • 【AI】专访 Braintrust CEO Ankur Goyal:为什么 AI 评测是产品 prototype 走向生产的唯一桥梁?
  • 大模型文生图和语音转换的调用以及向量和向量数据库RedisStack.
  • 做代练去什么网站安全合肥网站seo整站优化
  • 网站案例展示怎么做桂电做网站的毕设容易过嘛
  • QT-常用控件(一)
  • 网站开发选asp还是hph网站域名解析步骤
  • AI行业应用深度解析:从理论到实践的跨越
  • DeepMind 和罗光记团队 推出“帧链”概念:视频模型或将实现全面视觉理解
  • 外贸圈阿里巴巴微信seo什么意思
  • 【专业词汇】元认知
  • 有什么网站开发软件网页棋牌开发
  • Flutter与Dart结合AI开发实战
  • Easyx使用(数据可视化)
  • 基于单片机的大货车防偷油系统设计
  • JavaScript:神奇的ES6之旅
  • 延吉网站开发公司特别好的企业网站程序
  • Avalonia:现代跨平台UI开发的卓越之选
  • gta5网站正在建设阿里云网站建设与发布题库