需求:
现在我需要在util封装一个工具类,根据参数调用mapper获取数据,然后统一返回数据。
问题:
通过@Resource注解注入mapper,然后在方法中调用mapper时出现空指针异常,刚开始以为参数问题,然后打印输出发现mapper找不到,为null。
原因:
打印mapper为空,应该就是注入失败,普通类进行构造时此时还没有进行bean的注入,没有生成上下文对象。
初始化顺序:
静态变量 – 非静态成员变量 – 执行构造函数(此时通过@autowired修饰的成员变量为null) – bean注入 – 执行被@PostConstruct注解修饰的init函数
如果我们不希望bean在spring启动时就进行初始化,可以通过注解@lazy
进行延迟注入,只有第一次被引用时才会进行实例化。@lazy
可以加在@Bean
、@compoenent
、@Service
、@Configuration
、@Autowired
等注解上
解决办法:
1、 延迟注入 @PostConstruct(亲测)
2、 封装工具类(未测试) 参考文章:https://www.cnblogs.com/jichi/p/12158424.html
3、 在ssm中可以通过xml文件将普通类设置为一个bean对象(未测试)。
@PostConstruct注解的方法将会在依赖注入完成后被自动调用。此时便可将mapper对象正确注入给GetDeptIdUtil。
注意:调用mapper时不能直接xxxmapper,需要通过静态初始化后的类进行调用如下面代码中的getDeptIdUtil.vehicleDeptInfoMapper
@Component
public class GetDeptIdUtil {
@Resource
private VehicleInfoMapper vehicleInfoMapper;
//静态初始化
public static GetDeptIdUtil getDeptIdUtil;
/**
* 加上注解@PostConstruct,这样方法就会在Bean初始化之后被Spring容器执行
*/
@PostConstruct
public void init(){
getDeptIdUtil = this;
getDeptIdUtil.vehicleDeptInfoMapper = this.vehicleDeptInfoMapper;
}
public static String getDeptIdUtil(String deptId){
if (StringUtils.isNotBlank(deptId)){
String[] split = deptId.split(",");
for (String s : split) {
Long l = Long.parseLong(s);
System.out.println(getDeptIdUtil.vehicleDeptInfoMapper);
}
}
return null;
}
}
@PostConstruct虽好,但是要慎用,因为在bean初始化过程中,是顺序执行的,在执行完bean的构造方法后会执行@PostConstruct中的方法,如果方法逻辑处理时间长,会导致下一个bean的注入迟迟不能进行,进而增加应用的启动时间。@PostConstruct中逻辑处理时间较长时可以独立线程执行或者将初始化操作放在CommandLineRunner或ApplicationRunner的实现组件中。
Spring Boot:@PostConstruct虽好,也要慎用
下面放一张springboot启动结构图。
图片出自:https://www.jianshu.com/p/87f101d8ec41
参考博客:
https://www.jianshu.com/p/3a8f2dfd8445
https://blog.youkuaiyun.com/lxh_worldpeace/article/details/106789546
https://www.jianshu.com/p/87f101d8ec41
https://www.cnblogs.com/jichi/p/12158424.html
感谢博主的文章,也欢迎大家多多关注上述博主。