@Autowired注入失效问题分析

2019-06-042613

前言

最近在测试easyExcel工具类时 , 需要自定义一个Listener类用于执行对从excel表中读取到的数据进行入库操作(持久层框架为Mybatis-Plus) . 在程序运行过程中 , 发现通过@Autowired注解注入Mapper对象为null , 从而导致了执行插入记录操作时 报了空指针异常 , 具体代码如下 :

/**
 * @Author: WuKun
 * @Date: 2019/5/24 17:27
 */
@Component
public class ProductCmsExcelVOListener extends ExcelListener<ProductCmsExcelVO> {

    @Autowired
    private ProductMapper productMapper;

    @Override
    @Transactional
    public void doSomething(ProductCmsExcelVO object, AnalysisContext context) {
       //入库操作...
    }
}

问题定位

  • 首先确保该Listener类已添加@Component注解 √

  • Listener类已在@ComponentScan注解指定的扫描路径下 (ps. Spring Boot默认是从启动类所在位置往下扫描)

  • Mapper接口已在@MapperScan注解指定的扫描路径下 √

  • Listener对象 不能通过手动new 的方式创建 ×

由于我原来在创建ProductCmsExcelVOListener对象时 , 是通过ProductCmsExcelVOListener.class字节码对象的newInstance()方法去创建对象的 , 实质等价于直接new一个该对象 , 从而导致ProductCmsExcelVOListener 的Bean没有被 Spring 管理 , 这也是问题所在 .

解决方式

  • 在创建ProductCmsExcelVOListener对象时 , 同样通过@Autowired的方式注入 , 而不是自己手动new.
  • 当然也可以使用比较原始的方法进行去获取Bean , 如ApplicationContext 的getBean(beanName);的方式.

总结

@Autowired注入对象失效的主要有如下两种情况 :

  • 第一种如上所述 , 调用者本身不能直接通过new的方式创建 . 例如B是A中通过@Autowired注入的成员属性 , 当A是通过手动new的方式创建对象时 , B的注入会失效 .
  • 另一种情况如上面问题定位的第二点所述 , Spring Boot 默认Bean扫描策略是从Application启动类所在位置往下扫描 , 当项目存在多个Spring Boot 模块时 , 需要保证其他模块中添加了@Component注解的类已在Spring Boot的扫描路径范围内 , 必要时需要使用@ComponentScan("com.xx.xx")注解方式扩大Bean的扫描范围 , 而不是使用Spring Boot 默认的扫描策略 .

参考链接 :

分享
点赞4
打赏
上一篇:Docker常用命令笔记(一)
下一篇:IDEA JRebel 热部署插件——项目改动无需重启