非常好,阿杰 👍
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️⃣ 获取容器中任意 BeanapplicationContext.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,可能会被注入子容器或父容器
🧩 替代方案对于配置类、环境访问等,可用 @ValueEnvironmentAware@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