SpringBoot扫描不到组件?给你提供几种方案

简介: SpringBoot扫描不到组件?给你提供几种方案

最近接手一套基于SpringBoot项目,对项目进行重构调整,将公共部分抽离成子项目。在实践的过程中,发现抽离之后的模板中组件并没有被初始化。于是将排查解决过程中搜集到的方案及知识汇总分享给大家。

问题原因

问题的原因很简单,因多套系统的package命名不一致。比如业务系统的包命名为com.abc.xx,而公共(common)部分的包命名为com.efg.xx,引入公共jar包时默认是无法初始化的。image.png对于SpringBoot项目,我们知道扫描的路径从启动类所在包开始,扫描当前包及其子级包下的所有文件。上图如果启动类在com.abc包下,肯定是无法扫描到com.def包内的组件的。

场景延伸

SpringBoot的这个机制还延伸出另外两个场景。

第一个场景是如果SpringBoot的启动类放的包路径靠下,那么在它上级目录中的组件是无法被扫描并初始化的。新手往往会因放错位置导致启动时异常。

第二个场景是故意将一些不需要纳入SpringBoot容器的类放在其他包中,避免被SpringBoot容器加载。当然此时也可以使用ComponentScan来指定排除对应的包。















├── src│   ├── main│   │   ├── java│   │   │   └── com│   │   │       └── secbro│   │   │           ├── SpringBootMainApplication.java│   │   │           ├── controller│   │   │           │   └── DruidController.java│   │   │           ├── model│   │   │           │   └── Order.java│   │   │           └── service│   │   │               ├── OrderService.java│   │   │               └── impl│   │   │                   └── OrderServiceImpl.java

上述项目结构中,如果将类直接放在com目录或com目录的其他子目录下,默认是不会被初始化的。

通过@ComponentScan扫描

回到正题,遇到类似不被初始化的情况,我们可以使用的最简单的方案就是手动指定扫描包路径。

在启动类上的@SpringBootApplication注解内部集成了@ComponentScan注解。此时我们可以显示的指定扫描的包。








@SpringBootApplication@ComponentScan({"com.abc.xx","com.def.xx"})public class SpringBootMainApplication {  public static void main(String[] args) {    SpringApplication.run(SpringBootMainApplication.class, args);  }}

此种用法一定要先包含本项目要扫描的路径“com.abc.xx”,然后再在后面添加上common项目要扫描的路径“com.def.xx”。

如果其他项目不需要初始化common中的内容,则可不进行指定。

自定义@Enable****注解

上述方法虽然能够解决问题,但如果直接写包名,难免没有个统一的规范。此时可考虑使用@Enable类型的注解。

了解SpringBoot机制的朋友都知道,最重要的一个注解便是@EnableAutoConfiguration。类似的,我们定义一个可以通过注解之后便可使用的Enable注解。image.png定义配置类,在配置类中指定要扫描的包路径:

@Component
@ComponentScan("com.def.xx")
public class CommonConfig {
}

定义Enable注解类,并通过@Import导入配置类:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(CommonConfig.class)
public @interface EnableCommon {
}

然后,在启动类中便可使用@EnableCommon此注解来指定实例化对应的package。

@EnableCommon
@SpringBootApplication
public class SpringBootMainApplication {
// ...
}

在此过程中需要注意的是CommonConfig是位于common项目当中的。如果CommonConfig直接可被SpringBoot扫描到,那也就不需要EnableCommon注解了。

自定义starter

我们使用SpringBoot之所以方便,得益于它的特性之一便是可以使用已经集成好的starter。同样,我们也可以自定义一套starter来达到自动化配置的效果。

由于这种模式更适用于自动化集成某一个组件,并不太适合这里说的common公共项目。因此就不再代码演示,只说一下大概的思路。详细实例可参考我的新书《SpringBoot技术内幕:架构设计与实现原定义starter首先需要依赖自动配置的组件,也就是pom文件中添加如下配置:







<dependencies>  <dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-autoconfigure</artifactId>  </dependency></dependencies>

然后再定义具体的服务(或初始化)类,比如HelloWorldService以及该服务类初始化的参数类HelloWorldProperties。通过@ConfigurationProperties注解可以将Application中对应的属性初始化到类的属性中。

然后呢,再提供一个基于@ConditionalOnClass配置的HelloWorldAutoConfiguration类,指定当HelloWorldService存在于类路径时,便会进行初始化。

最后一步,在META-INF目录下创建spring.factories,启动添加类似如下配置:



# Auto Configureorg.springframework.boot.autoconfigure.EnableAutoConfiguration=com.secbro.HelloWorldAutoConfiguration

该类是为SpringBoot提供的扫描入口。

此时,当其他项目需要该starter时,直接引入便可注入使用HelloWorldService类了。

关于此处建议大家专门看一篇相关的实战文章,可以更好的理解。这里只提供了一个大概的思路。

小结

关于SpringBoot的@ComponentScan基本上已经可以满足需求了,第二种方案是基于@ComponentScan的改进方案。而第三种方案更多的是基于SpringBoot的核心原理来处理的。当然最好是避免同一个项目使用多个顶级package。

通过本篇文章的脉络,我们可以看到一种学习的方式,通过一个知识点或一个实战中的问题,可以逐步将知识从点扩充到面,这样不仅能加大学习的范围,也能构建更牢固的知识图谱。


目录
相关文章
|
1月前
|
人工智能 自然语言处理 前端开发
SpringBoot + 通义千问 + 自定义React组件:支持EventStream数据解析的技术实践
【10月更文挑战第7天】在现代Web开发中,集成多种技术栈以实现复杂的功能需求已成为常态。本文将详细介绍如何使用SpringBoot作为后端框架,结合阿里巴巴的通义千问(一个强大的自然语言处理服务),并通过自定义React组件来支持服务器发送事件(SSE, Server-Sent Events)的EventStream数据解析。这一组合不仅能够实现高效的实时通信,还能利用AI技术提升用户体验。
175 2
|
1月前
|
easyexcel Java UED
SpringBoot中大量数据导出方案:使用EasyExcel并行导出多个excel文件并压缩zip后下载
在SpringBoot环境中,为了优化大量数据的Excel导出体验,可采用异步方式处理。具体做法是将数据拆分后利用`CompletableFuture`与`ThreadPoolTaskExecutor`并行导出,并使用EasyExcel生成多个Excel文件,最终将其压缩成ZIP文件供下载。此方案提升了导出效率,改善了用户体验。代码示例展示了如何实现这一过程,包括多线程处理、模板导出及资源清理等关键步骤。
|
1月前
|
Java 数据库连接 mybatis
Springboot整合Mybatis,MybatisPlus源码分析,自动装配实现包扫描源码
该文档详细介绍了如何在Springboot Web项目中整合Mybatis,包括添加依赖、使用`@MapperScan`注解配置包扫描路径等步骤。若未使用`@MapperScan`,系统会自动扫描加了`@Mapper`注解的接口;若使用了`@MapperScan`,则按指定路径扫描。文档还深入分析了相关源码,解释了不同情况下的扫描逻辑与优先级,帮助理解Mybatis在Springboot项目中的自动配置机制。
135 0
Springboot整合Mybatis,MybatisPlus源码分析,自动装配实现包扫描源码
|
1月前
|
存储 NoSQL Java
Spring Boot项目中使用Redis实现接口幂等性的方案
通过上述方法,可以有效地在Spring Boot项目中利用Redis实现接口幂等性,既保证了接口操作的安全性,又提高了系统的可靠性。
40 0
|
3月前
|
SQL JavaScript 前端开发
vue中使用分页组件、将从数据库中查询出来的数据分页展示(前后端分离SpringBoot+Vue)
这篇文章详细介绍了如何在Vue.js中使用分页组件展示从数据库查询出来的数据,包括前端Vue页面的表格和分页组件代码,以及后端SpringBoot的控制层和SQL查询语句。
vue中使用分页组件、将从数据库中查询出来的数据分页展示(前后端分离SpringBoot+Vue)
|
2月前
|
缓存 监控 Java
造轮子能力大提升:基于SpringBoot打造高性能缓存组件
在快节奏的软件开发领域,"不重复造轮子" 常常被视为提高效率的金科玉律。然而,在某些特定场景下,定制化的高性能缓存组件却是提升系统性能、优化用户体验的关键。今天,我们将深入探讨如何利用SpringBoot框架,从零开始打造一款符合项目需求的高性能缓存组件,分享我在这一过程中的技术心得与学习体会。
70 6
|
3月前
|
安全 Java Spring
Spring Boot 关闭 Actuator ,满足安全工具扫描
Spring Boot 关闭 Actuator ,满足安全工具扫描
469 0
|
4月前
|
机器学习/深度学习 人工智能 文字识别
文本,文字扫描01,OCR文本识别技术展示,一个安卓App,一个简单的设计,文字识别可以应用于人工智能,机器学习,车牌识别,身份证识别,银行卡识别,PaddleOCR+SpringBoot+Andr
文本,文字扫描01,OCR文本识别技术展示,一个安卓App,一个简单的设计,文字识别可以应用于人工智能,机器学习,车牌识别,身份证识别,银行卡识别,PaddleOCR+SpringBoot+Andr
|
5月前
|
缓存 NoSQL Java
案例 采用Springboot默认的缓存方案Simple在三层架构中完成一个手机验证码生成校验的程序
案例 采用Springboot默认的缓存方案Simple在三层架构中完成一个手机验证码生成校验的程序
110 5
|
5月前
|
NoSQL 前端开发 Java
技术笔记:springboot分布式锁组件spring
技术笔记:springboot分布式锁组件spring
55 1
下一篇
无影云桌面