一.工具类静态方法调用使用@Autowired注入的bean导致的空指针问题
-
问题描述:在工具类中使用@Autowired注入的bean报空指针
-
原因:静态变量,静态方法不是对象的属性,属于class的;普通方法才是属于对象;spring注入是在容器中实例化对象,静态类,方法的加载优于@Autowired的加载(Java变量的初始化顺序为:静态变量或静态语句块–>实例变量或初始化语句块–>构造方法–>@Autowired> @PostConstruct)
解决办法:
- @PostConstruct:被@PostConstruct修饰的方法会在服务器加载Servle的时候运行,并且只会被服务器执行一次。PostConstruct在构造函数之后执行,init()方法之前执行。
/**
**@Component注解必不可少
**/
@Component
public class EnCodeUtils {
@Autowired
private AlarmRuleMapper alarmRuleMapper;
private static EnCodeUtils enCodeUtils;
@PostConstruct
public void init() {
enCodeUtils = this;
enCodeUtils.alarmRuleMapper = this.alarmRuleMapper;
}
- 第二种方法,就是在构造函数上使用@Autowired。
@Component
public class EnCodeUtils {
private static AlarmRuleMapper alarmRuleMapper;
public EnCodeUtils() {
EnCodeUtils.alarmRuleMapper = this.alarmRuleMapper;
}
- 第三种方法:spring配置文件需扫描工具类包
@SpringBootApplication(scanBasePackages = {"com.bigdata.servicebus.util"})
二.访问类中@Autowired注入的成员变量导致空指针
- 问题描述:在除三层调用的地方使用@Autowired调用其他类对象
- 原因:一个内含有@Autowired注解的Bean,我们必须要通过Spring的方式来获得这个Bean,而不能自己new一个。因为自己new出来的bean无法通过Spring容器来获得自己需要的bean.可以简单的理解为,要就全都使用Spring容器来管理,要不都不用,你自己new的东西没有进入Spring容器的门票
解决方案:
- 方法一:传参
public class ServiceCallsImpl implements Strategy {
private AnalysisService analysisService;
public ServiceCallsImpl(AnalysisService analysisService) {
this.analysisService = analysisService;
}
- 方法二:使用反射
public class ServiceCallsImpl implements Strategy {
private AnalysisService analysisService;
public ServiceCallsImpl() throws ClassNotFoundException {
this.analysisService = this.getClass().getClassLoader().loadClass("com.bigdata.servicebus.analysis.record.AnalysisService").newInstance();
}
- 方法三:接口传参,在需要该对象的地方实现该接口,传参导入
public interface Strategy {
boolean alarmDeal(AlarmLeft alarmLeft, RequestRecord requestRecord, MongoTemplate mongoTemplate);
void setAnalysisService(AnalysisService analysisService);
}