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

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: SpringBoot【问题 01】借助@PostConstruct解决使用@Component注解的类用@Resource注入Mapper接口为null的问题(原因解析+解决方法)

1. 说明

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

2. 代码实现

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

/**
 * 集中管理非单表操作的SQL
 */
@Mapper
public interface ComplexSqlMapper {
    // 查询 view_manager 表全部数据
    @Select(" select * from view_manager ")
    List<ViewEntity> getViewManagerAllList();
}

下面是管理类,这里没有使用Doc注释:

/**
 * 查询并处理 view_manager 表数据(为了简洁这里是示例代码 真正的处理要比这个复杂)
 */
@Component
public class ViewManager {
  // Mapper 注入
  @Resource
    private ComplexSqlMapper complexSqlMapper;
    // 处理结果保存
    private Map<String, String> views = new HashMap();
    // 初始化时查询 view_manager 表数据
    private ViewManager() {
      List<ViewEntity> 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<String, String> views = new HashMap();
    @PostConstruct
    private void init() {
        List<ViewEntity> viewEntityList= complexSqlMapper.getViewManagerAllList();
        viewEntityList.forEach(ve-> {
            views.put(ve.getId(), ve.getName());
        });
  }
}

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

目录
相关文章
|
6天前
|
Java 开发者 Spring
【SpringBoot 异步魔法】@Async 注解:揭秘 SpringBoot 中异步方法的终极奥秘!
【8月更文挑战第25天】异步编程对于提升软件应用的性能至关重要,尤其是在高并发环境下。Spring Boot 通过 `@Async` 注解简化了异步方法的实现。本文详细介绍了 `@Async` 的基本用法及配置步骤,并提供了示例代码展示如何在 Spring Boot 项目中创建与管理异步任务,包括自定义线程池、使用 `CompletableFuture` 处理结果及异常情况,帮助开发者更好地理解和运用这一关键特性。
50 1
|
15天前
|
XML Java 测试技术
Spring5入门到实战------17、Spring5新功能 --Nullable注解和函数式注册对象。整合JUnit5单元测试框架
这篇文章介绍了Spring5框架的三个新特性:支持@Nullable注解以明确方法返回、参数和属性值可以为空;引入函数式风格的GenericApplicationContext进行对象注册和管理;以及如何整合JUnit5进行单元测试,同时讨论了JUnit4与JUnit5的整合方法,并提出了关于配置文件加载的疑问。
Spring5入门到实战------17、Spring5新功能 --Nullable注解和函数式注册对象。整合JUnit5单元测试框架
|
2天前
|
缓存 Java 数据库连接
Spring Boot奇迹时刻:@PostConstruct注解如何成为应用初始化的关键先生?
【8月更文挑战第29天】作为一名Java开发工程师,我一直对Spring Boot的便捷性和灵活性着迷。本文将深入探讨@PostConstruct注解在Spring Boot中的应用场景,展示其在资源加载、数据初始化及第三方库初始化等方面的作用。
13 0
|
1天前
|
前端开发 数据可视化 Java
SpringBoot的4中常见入参形式错误解析
在使用SpringBoot进行前后端接口对接时,常遇到如500、400等请求错误,本文总结了四个常见的复杂请求类型及其解决方案,包括实体嵌套List提交、普通文件上传、List提交及数组Array提交,详细展示了正确的前端与后端代码实现,帮助开发者避免常见错误,提高开发效率。
12 0
SpringBoot的4中常见入参形式错误解析
|
10天前
|
Java Maven Spring
SpringBoot 系列之 Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resource
这篇文章描述了在使用Maven构建Spring Boot项目时遇到的`maven-resources-plugin`插件版本问题导致的编译失败,并提供了通过修改插件版本至3.1.0来解决这个问题的方法。
SpringBoot 系列之 Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resource
|
15天前
|
Java 数据安全/隐私保护 Spring
揭秘Spring Boot自定义注解的魔法:三个实用场景让你的代码更加优雅高效
揭秘Spring Boot自定义注解的魔法:三个实用场景让你的代码更加优雅高效
|
11天前
|
Java Spring
Spring boot +Thymeleaf 本地图片加载失败(图片路径)的问题及解决方法
这篇文章详细讲解了在Spring Boot应用程序中本地图片无法加载的问题原因,并提供了两个示例来说明如何通过使用正确的相对路径或Thymeleaf语法来解决图片路径问题。
|
15天前
|
XML Java 数据库
Spring5入门到实战------15、事务操作---概念--场景---声明式事务管理---事务参数--注解方式---xml方式
这篇文章是Spring5框架的实战教程,详细介绍了事务的概念、ACID特性、事务操作的场景,并通过实际的银行转账示例,演示了Spring框架中声明式事务管理的实现,包括使用注解和XML配置两种方式,以及如何配置事务参数来控制事务的行为。
Spring5入门到实战------15、事务操作---概念--场景---声明式事务管理---事务参数--注解方式---xml方式
|
15天前
|
XML 数据库 数据格式
Spring5入门到实战------14、完全注解开发形式 ----JdbcTemplate操作数据库(增删改查、批量增删改)。具体代码+讲解 【终结篇】
这篇文章是Spring5框架的实战教程的终结篇,介绍了如何使用注解而非XML配置文件来实现JdbcTemplate的数据库操作,包括增删改查和批量操作,通过创建配置类来注入数据库连接池和JdbcTemplate对象,并展示了完全注解开发形式的项目结构和代码实现。
Spring5入门到实战------14、完全注解开发形式 ----JdbcTemplate操作数据库(增删改查、批量增删改)。具体代码+讲解 【终结篇】
|
15天前
|
XML Java 数据格式
Spring5入门到实战------8、IOC容器-Bean管理注解方式
这篇文章详细介绍了Spring5框架中使用注解进行Bean管理的方法,包括创建Bean的注解、自动装配和属性注入的注解,以及如何用配置类替代XML配置文件实现完全注解开发。
Spring5入门到实战------8、IOC容器-Bean管理注解方式

热门文章

最新文章

推荐镜像

更多
下一篇
云函数