【SpringBoot】ApplicationContextAware 与 @Autowired 注解效果是一样,但是时机不一样

一、区别

  • 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 getBean(Class clazz){
        return getApplicationContext().getBean(clazz);
    }
 
    //通过name,以及Clazz返回指定的Bean
    public static  T getBean(String name,Class 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 中抛出对应的异常,来提示给开发人员

【SpringBoot】ApplicationContextAware 与 @Autowired 注解效果是一样,但是时机不一样_第1张图片

  •  如果将 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注解

你可能感兴趣的:(spring,boot,java,spring)