栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

【Java报错】借助@PostConstruct解决使用@Component注解的类用@Resource注入Mapper接口为null的问题(原因解析+解决方法)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【Java报错】借助@PostConstruct解决使用@Component注解的类用@Resource注入Mapper接口为null的问题(原因解析+解决方法)

1. 说明

有些时候我们需要一个管理类,类似 xxxManager 来处理共享的基础数据,它要在项目启动时就进行初始化且查询数据库,而且查询语句不复杂,写一整套的Service或者使用MyBatis的查询API有点儿繁琐,此时写一个简单的Mapper接口就优雅许多。

2. 代码实现

为了简洁,删掉部分不必要的备注,下边是Mapper接口:

@Mapper
public interface ComplexSqlMapper {
    // 查询 view_manager 表全部数据
    @Select(" select * from view_manager ")
    List getViewManagerAllList();
}

下面是管理类,避免冗余这里没有doc注释:

@Component
public class ViewManager {
	// Mapper 注入
	@Resource
    private ComplexSqlMapper complexSqlMapper;
    // 处理结果保存
    private Map views = new HashMap();
    // 初始化时查询 view_manager 表数据
    private ViewManager() {
    	List viewEntityList= complexSqlMapper.getViewManagerAllList();
    	// 处理数据
    	viewEntityList.forEach(ve-> {
            views.put(ve.getId(), ve.getName());
        });
    }
}
3. 原因解析

项目启动时有NPE,debug才发现 complexSqlMapper 是null。我首先想到的是Mapper文件没有被检测到,然后确认了启动类里的 org.mybatis.spring.annotation.MapperScan 信息:

@SpringBootApplication
@MapperScan(basePackages = "com.example.demo.**.mapper")
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

并没有写错路径,那我们仔细回看 ViewManager 类就会发现 complexSqlMapper 是当作类的成员变量被注入的,那也就是说需要先实例化 ViewManager 类然后再注入 complexSqlMapper,可是我们在类的构造器里就调用了 complexSqlMapper 此时构造器没有执行完,ViewManager 也就没被实例化,那么 complexSqlMapper 自然是个null。至此通过构造器使用 Mapper 查询数据的计划落空了。

4. 问题解决

那就没有方法了吗 ❓ 怎么可能 ❗️ Spring早就想到了你想到的  使用 @PostConstruct 注解的方法将会在依赖注入完成后被自动调用。

改造后的代码【这里只贴出核心代码 无关备注也省略了】

@Component
public class ViewManager {

 	@Resource
    private ComplexSqlMapper complexSqlMapper;
    private Map views = new HashMap();

    @PostConstruct
    private void init() {
        List viewEntityList= complexSqlMapper.getViewManagerAllList();
        viewEntityList.forEach(ve-> {
            views.put(ve.getId(), ve.getName());
        });
	}
}

改造后的代码,项目启动时由于 @Component 注解,ViewManager 类会被实例化并交给容器管理,此时使用的是 ViewManager 类的无参构造器。而 @PostConstruct 注解的 init 方法会待 complexSqlMapper 注入成功后调用。至此,xxxManager 的功能得以实现。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/440038.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号