一、区别
- ApplicationContextAware 是一个接口,它提供一个方法 setApplicationContext ,当 spring 注册完成之后,会把 ApplicationContext 对象以参数的方式传递到方法里,在方法里我们可以实现自己的逻辑,去获取自己的 bean,当前对接的断言等;一般用在被封装的工具包, starter 包中,方便给其它开发人员调用。
- @Autowired 是直接给开发人员使用的,直接注入对接类型的 bean 的,开箱即用,对应的注解还有 @Qualifier,或者直接使用 @Resource 注解来实现按 beanName 的注入。
二、案例
1、LindContext 组件
@Component
public class LindContext {
    public void print() {
        System.out.println("lind-context print.");
    }
}2、LindAware 组件
/**
 * 获取 spring 容器,以访问容器中定义的其它 bean
 */
@Component
@Slf4j
public class LindAware implements ApplicationContextAware {
 
    // Spring 应用上下文环境
    private static ApplicationContext applicationContext;
    private LindContext lindContext;
    public void contextPrint() {
        this.lindContext.print();
    }
 
    /**
     * 重写接口的方法,该方法的参数为框架自动加载的IOC容器对象
     * 该方法在启动项目的时候会自动执行,前提是该类上有IOC相关注解,例如@Component
     * @param applicationContext ioc容器
     * @throws BeansException e
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        // 将框架加载的ioc赋值给全局静态ioc
        LindAware.applicationContext = applicationContext;
        if (LindAware.applicationContext.geetBeansOfType(LindContext.class).isEmpty()) {
            throw new IllegalArgumentException("未加载或者未发现 LindContext 的 bean,请保证它可以正常加载到 spring 容器。")
        }
        this.lindContext = LindAware.applicationContext.getBean(LindContext.class);
 
        log.info("==================ApplicationContext加载成功==================");
    }
 
    //获取applicationContext
    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }
 
    /**
     * 获取对象
     * @param name
     * @return Object 一个以所给名字注册的 bean 的实例(service 注解方式,自动生成以首字母小写的类名为 bean name)
     */
    public static Object getBean(String name){
        return getApplicationContext().getBean(name);
    }
 
    //通过class获取Bean.
    public static <T> T getBean(Class<T> clazz){
        return getApplicationContext().getBean(clazz);
    }
 
    //通过name,以及Clazz返回指定的Bean
    public static <T> T getBean(String name,Class<T> clazz){
        return getApplicationContext().getBean(name, clazz);
    }
}3、controller
public class HelloController {
    @Autowired
    private LindAware lindAware;
    @PostMapping("/test2")
    public String test2() {
        lindAware.contextPrint();
        return "test2 aware success!";
    }
}4、测试接口
localhost:8080/testUtils/test2
返回结果:
"test2 aware success!"三、总结
- 如果将 LindContext 类中 @Component 注解去掉,没有将该 bean 注册到 spring 容器时,调用接口时会在 LindAware 中抛出对应的异常,来提示给开发人员

- 如果将 LindAware 类中 this.lindContext = LindAware.applicationContext.getBean(LindContext.class); 去掉,调用接口时,会报空指针异常,原因是 LindAware 类中 lindContext 是 null,LindContext 该 bean 没有注入到 LindAware 类中。
java.lang.NullPointerException: null
	at com.example.demo.utils.LindAware.contextPrint(LindAware.java:25) ~[classes/:na]
	at com.example.demo.controller.HelloController.test2(HelloController.java:32) ~[classes/:na]
- 如果将 LindAware 类中 this.lindContext = LindAware.applicationContext.getBean(LindContext.class); 去掉,在 private LindContext lindContext; 添加上 @Autowired 注解,那么调用接口,是能正常返回结果的。
- 通过 ApplicationContextAware 拿到的 ApplicationContext,和通过 @Resource 或者 @Autowired 拿到的 ApplicationContext,效果是一样的,时机不一样,但是ApplicationContext只有一个。
四、参考文档
springboot~ApplicationContextAware与@Autowired注解



















