一、区别
- 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注解