非常好,阿杰 👍ApplicationContextAware
是 Spring 框架中非常重要的一个 Aware 接口,它能让 Bean 在初始化阶段获取到当前的 Spring 容器(ApplicationContext),从而可以手动获取其他 Bean、发布事件、访问环境信息等。
下面我给你讲一个 从原理 → 用法 → 示例 → 注意事项 的完整讲解。
🌱 一、什么是 ApplicationContextAware
ApplicationContextAware
是 Spring 提供的一个回调接口:
当一个 Bean 实现了这个接口后,Spring 容器在初始化它时会自动调用该接口的 setApplicationContext()
方法,把当前的 ApplicationContext
传给它。
🧩 二、接口定义
package org.springframework.context;
public interface ApplicationContextAware {
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}
👉 容器在 Bean 初始化(属性注入后、初始化前)会自动调用该方法。
⚙️ 三、工作原理
Spring 在创建 Bean 的生命周期中,检测到一个 Bean 实现了 ApplicationContextAware
接口,就会由 ApplicationContextAwareProcessor
(一个特殊的 BeanPostProcessor)在 populateBean() → initializeBean() 过程中调用:
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware) bean).setApplicationContext(this);
}
💡 四、典型用法场景
场景 | 用法 |
---|---|
1️⃣ 获取容器中任意 Bean | 用 applicationContext.getBean(Class) 获取其他 Bean |
2️⃣ 获取应用配置(如环境变量) | applicationContext.getEnvironment() |
3️⃣ 发布事件 | applicationContext.publishEvent() |
4️⃣ 获取资源文件 | applicationContext.getResource("classpath:...") |
5️⃣ 全局保存 ApplicationContext(工具类静态调用) | 常见于工具类或非 Spring 管理的类中 |
🧠 五、简单示例
✅ 示例:获取容器对象并调用其他 Bean
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
@Component
public class MyContextAware implements ApplicationContextAware {
private static ApplicationContext context;
// 当Spring容器初始化此Bean时自动调用
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("✅ ApplicationContext 已注入");
context = applicationContext;
}
// 提供静态方法,方便其他类访问Spring容器
public static ApplicationContext getContext() {
return context;
}
// 获取任意Bean
public static <T> T getBean(Class<T> clazz) {
return context.getBean(clazz);
}
}
✅ 示例:在非Spring Bean中获取Bean
public class ExternalClass {
public void doSomething() {
// 非Spring管理类也能拿到Spring Bean
UserService userService = MyContextAware.getBean(UserService.class);
userService.sayHello();
}
}
🧩 六、结合事件发布使用
@Component
public class EventPublisher implements ApplicationContextAware {
private ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
this.context = applicationContext;
}
public void publishCustomEvent(String msg) {
context.publishEvent(new CustomEvent(this, msg));
}
}
⚠️ 七、注意事项
注意点 | 说明 |
---|---|
🚫 不推荐滥用 | 频繁直接访问容器会破坏 IOC 原则,推荐用 @Autowired 注入 |
⚙️ 执行时机 | 在 Bean 初始化早期执行(postProcessBeforeInitialization 前) |
🧵 多容器环境 | 若有多个 ApplicationContext,可能会被注入子容器或父容器 |
🧩 替代方案 | 对于配置类、环境访问等,可用 @Value 、EnvironmentAware 、@EventListener 更优雅 |
🧾 八、输出顺序示例(日志演示)
假设一个 Bean 同时实现多个 Aware 接口:
@Component
public class MyAwareBean implements BeanNameAware, ApplicationContextAware, InitializingBean {
@Override
public void setBeanName(String name) {
System.out.println("1️⃣ BeanNameAware: " + name);
}
@Override
public void setApplicationContext(ApplicationContext ctx) {
System.out.println("2️⃣ ApplicationContextAware 被调用");
}
@Override
public void afterPropertiesSet() {
System.out.println("3️⃣ Bean 初始化完毕");
}
}
输出顺序为:
1️⃣ BeanNameAware: myAwareBean
2️⃣ ApplicationContextAware 被调用
3️⃣ Bean 初始化完毕
✅ 九、小结
阶段 | 方法 | 作用 |
---|---|---|
Aware 回调 | setApplicationContext() | 获取容器引用 |
优点 | 可在非Spring类中间接访问 Bean | |
缺点 | 增强耦合,违背 IoC 原则,慎用 | |
替代方案 | @Autowired 、@EventListener 、@Value |
发表回复