前言
一般情况下,可以用 @Service @Repository等注解将类交由spring管理,再用 @Autowired 或 @Resource 来调用对象。
但有时候会遇到在非spring管理的类中注入spring管理的对象,比如监听器Listener,Listener的生命周期是由servlet管理的,而spring容器中的bean是由spring管理的,导致servlet容器不认得 @Autowired 注解,最终注入失败
错误使用
在最近用 easyexcel 读取数据导数据库的实际使用中,一开始就是用 @Component 来标识 SubjectExcelListener 监听器,用 @Autowired 在监听器内部调用service,以及用 @Autowired 调用 SubjectExcelListener ,最终导致空指针异常,简单说就是listener无法交由spring管理
CategoryExcelListener.class
@Component
public class CategoryExcelListener extends AnalysisEventListener<CategoryData> {
@Autowired
CategoryService categoryService;
CategoryServiceImpl.class
@Autowired
CategoryExcelListener categoryExcelListener ;
@Override
public void saveCategory(MultipartFile file) {
try {
InputStream inputStream = file.getInputStream();
EasyExcel.read(inputStream, CategoryData.class, categoryExcelListener).sheet().doRead();
} catch (IOException e) {
e.printStackTrace();
}
}
最终报错空指针,原因前言说过了
正确使用
既然Listener无法交由spring管理,所以我们在 EasyExcel.read() 方法中传入监听器可以传 new CategoryExcelListener(categoryService),就是传带参构造器,将service对象通过构造器传过去,以使用service。
CategoryServiceImpl.class
@Autowired
CategoryService categoryService ;
@Override
public void saveCategory(MultipartFile file) {
try {
InputStream inputStream = file.getInputStream();
EasyExcel.read(inputStream, CategoryData.class, new CategoryExcelListener(categoryService)).sheet().doRead();
} catch (IOException e) {
e.printStackTrace();
}
}
public class CategoryExcelListener extends AnalysisEventListener<CategoryData> {
CategoryService categoryService;
public CategoryExcelListener() {}
public CategoryExcelListener(CategoryService categoryService) {
this.categoryService = categoryService;
}
这样即可在监听器中正常使用service完成操作
注意
在 CategoryServiceImpl类中, EasyExcel.read(inputStream, CategoryData.class, new CategoryExcelListener(categoryService)).sheet().doRead();
中,带参构造器中的参数 categoryService 不能用this来替代service,否则也会空指针
如有说错的地方,欢迎指出