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

简介: 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 的功能得以实现。

目录
相关文章
|
8月前
|
XML 安全 Java
使用 Spring 的 @Aspect 和 @Pointcut 注解简化面向方面的编程 (AOP)
面向方面编程(AOP)通过分离横切关注点,如日志、安全和事务,提升代码模块化与可维护性。Spring 提供了对 AOP 的强大支持,核心注解 `@Aspect` 和 `@Pointcut` 使得定义切面与切入点变得简洁直观。`@Aspect` 标记切面类,集中处理通用逻辑;`@Pointcut` 则通过表达式定义通知的应用位置,提高代码可读性与复用性。二者结合,使开发者能清晰划分业务逻辑与辅助功能,简化维护并提升系统灵活性。Spring AOP 借助代理机制实现运行时织入,与 Spring 容器无缝集成,支持依赖注入与声明式配置,是构建清晰、高内聚应用的理想选择。
770 0
|
8月前
|
缓存 监控 Java
SpringBoot @Scheduled 注解详解
使用`@Scheduled`注解实现方法周期性执行,支持固定间隔、延迟或Cron表达式触发,基于Spring Task,适用于日志清理、数据同步等定时任务场景。需启用`@EnableScheduling`,注意线程阻塞与分布式重复问题,推荐结合`@Async`异步处理,提升任务调度效率。
1259 128
|
8月前
|
Java 测试技术 API
将 Spring 的 @Embedded 和 @Embeddable 注解与 JPA 结合使用的指南
Spring的@Embedded和@Embeddable注解简化了JPA中复杂对象的管理,允许将对象直接嵌入实体,减少冗余表与连接操作,提升数据库设计效率。本文详解其用法、优势及适用场景。
434 126
|
9月前
|
XML JSON Java
Spring框架中常见注解的使用规则与最佳实践
本文介绍了Spring框架中常见注解的使用规则与最佳实践,重点对比了URL参数与表单参数的区别,并详细说明了@RequestParam、@PathVariable、@RequestBody等注解的应用场景。同时通过表格和案例分析,帮助开发者正确选择参数绑定方式,避免常见误区,提升代码的可读性与安全性。
|
8月前
|
Java 测试技术 数据库
使用Spring的@Retryable注解进行自动重试
在现代软件开发中,容错性和弹性至关重要。Spring框架提供的`@Retryable`注解为处理瞬时故障提供了一种声明式、可配置的重试机制,使开发者能够以简洁的方式增强应用的自我恢复能力。本文深入解析了`@Retryable`的使用方法及其参数配置,并结合`@Recover`实现失败回退策略,帮助构建更健壮、可靠的应用程序。
939 1
使用Spring的@Retryable注解进行自动重试
|
7月前
|
XML Java 应用服务中间件
【SpringBoot(一)】Spring的认知、容器功能讲解与自动装配原理的入门,带你熟悉Springboot中基本的注解使用
SpringBoot专栏开篇第一章,讲述认识SpringBoot、Bean容器功能的讲解、自动装配原理的入门,还有其他常用的Springboot注解!如果想要了解SpringBoot,那么就进来看看吧!
707 2
|
8月前
|
XML Java 数据格式
常用SpringBoot注解汇总与用法说明
这些注解的使用和组合是Spring Boot快速开发和微服务实现的基础,通过它们,可以有效地指导Spring容器进行类发现、自动装配、配置、代理和管理等核心功能。开发者应当根据项目实际需求,运用这些注解来优化代码结构和服务逻辑。
526 12
|
JSON Java fastjson
微服务——SpringBoot使用归纳——Spring Boot返回Json数据及数据封装——使用 fastJson 处理 null
本文介绍如何使用 fastJson 处理 null 值。与 Jackson 不同,fastJson 需要通过继承 `WebMvcConfigurationSupport` 类并覆盖 `configureMessageConverters` 方法来配置 null 值的处理方式。例如,可将 String 类型的 null 转为 &quot;&quot;,Number 类型的 null 转为 0,避免循环引用等。代码示例展示了具体实现步骤,包括引入相关依赖、设置序列化特性及解决中文乱码问题。
674 0
|
8月前
|
传感器 Java 数据库
探索Spring Boot的@Conditional注解的上下文配置
Spring Boot 的 `@Conditional` 注解可根据不同条件动态控制 Bean 的加载,提升应用的灵活性与可配置性。本文深入解析其用法与优势,并结合实例展示如何通过自定义条件类实现环境适配的智能配置。
432 0
探索Spring Boot的@Conditional注解的上下文配置

推荐镜像

更多
  • DNS