上篇文章有讲解过spring为什么不推荐使用@Autowired,个人觉得讲解的还是比较白话易懂的,毕竟我也不是科班出身。本来这片文章是想讲解缓存和数据库数据一致性问题的,但是这个问题比较难讲解,短篇幅也很难讲解完。加上今天刚好在群里看见有人在问spring注入为null这个问题,就想写先写一篇关于这个的吧。
spring注入为null,我想大部分java程序员都碰到过吧。关于这方面的问题我看网上有很多方面的原因,但是在我看来就三个大的原因:1、注入的bean没有被容器管理。2、调用bean的方法的时候容器还没初始化完成。3、使用new的方法创建对象。
一、注入的bean没有被容器管理的情况:
1、没有添加注解,例如@Service、@Component等。解决方法也很简单,就是在想要注入的类上加上注解。
2、添加了注解但是没有被Spring扫描到容器中。springboot扫描的是启动类的默认的包扫描范围是启动类的同级目录和子目录下的Bean。解决方法也简单,如果你的注入类不在默认的包扫描范围下,你就需要在启动类上加上@ComponentScans
@ComponentScans(value = {com.***.***})
二、调用bean的方法的时候容器还没初始化完成:
这种情况就我目前知道的也就三种。
1、注入的属性被final修饰的。关于这种我之前已经在上一篇文章中讲解过了,这里就不过多再说。有兴趣可以去看看spring为什么不推荐使用@Autowired-CSDN博客
2、注入的属性static被修饰的时候,这种其实也是由于静态变量或静态语句块 –> 实例变量或初始化语句块 –> 构造方法 -> @Autowired 的加载顺序导致的。你可以通过构造方法注入去解决大多数情况下注入为null的问题,但是无法解决静态代码块中调用的空指针异常问题。静态代码块注入为null的解决方法可以通过ClassPathXmlApplicationContext这个类去解决。
static {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
testService=context.getBean(TestService.class);
testService.test();
}
这种方法需要在配置文件applicationContext.xml配置文件中去配置你需要的bean。
<bean id="testService" class="com.***.***.service.impl.TestServiceImpl"></bean>
3、在过滤器中注入时。这个产生的原因也是拦截器(过滤器)加载是在springcontext创建之前完成的。解决方法就是再这之前去进行注入。在类中加上方法:
/**
* 由于在过滤器中无法直接通过Autowired获取Bean,因此需要通过spring上下文来获取IOC管理的实体类
*/
public <T> T getBean(Class<T> clazz, HttpServletRequest request){
WebApplicationContext applicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext());
return applicationContext.getBean(clazz);
}
然后在调用注入类的方法前
//这里是使用redisconfig进行一个示例
RedisConfig redisConfig = getBean(RedisConfig.class, req);
redisConfig.getHost()
三、使用new的方法创建对象
这个比较好理解就不过多解释,基本也没人会这样用吧现在。