2.2 Spring boot 配置分析 - 通过工厂方式注入bean

Spring Boot配置分析:通过FactoryBean注入Bean实战
本文详细介绍了如何在Spring5中利用FactoryBean实现bean的注入。从创建Maven工程、添加Spring5依赖,到创建bean、自定义FactoryBean、配置类以及主类,一步步展示具体步骤。通过这种方式,可以自定义bean的名字并在应用上下文中获取。

本章主要写的是 Spring5 通过实现FactoryBean 的方式 来注入Bean 。
初始条件:
1. Java version : 1.8
2. maven vesion: 1.3.9

快速链接: 2.1 Spring5 快速入门

第一步:创建一个简单结构(quickstart)的 Maven 工程
创建 Maven 工程

第二步:将 Spring5 的依赖加入项目的 POM 文件中:

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.0.0.RELEASE
<think>我们有两个问题需要解决:1.公共模块定义的对象在服务A模块引入后部分类无法找到2.公共模块构建时出现Failedtoexecutegoalorg.springframework.boot:spring-boot-maven-plugin:2.3.2.RELEASE:repackage(unabletofindmainclass)首先,分析问题1:公共模块中部分类无法找到原因:1.1公共模块打包时未包含这些类(构建问题)1.2公共模块被依赖时,这些类没有被正确引入(依赖配置、包扫描等问题)其次,问题2:公共模块构建失败,错误信息为repackage失败,无法找到主类原因分析2.1公共模块作为普通的jar库,不应该是一个可执行的SpringBoot应用。因此,它不需要主类。但spring-boot-maven-plugin的repackage目标默认会将项目打包为可执行jar,这需要一个主类。2.2在公共模块中错误地使用了spring-boot-maven-plugin,并且没有配置主类(或者配置了但未找到)。解决方案思路:对于问题2:我们不应该对公共模块使用spring-boot-maven-plugin的repackage目标。通常,公共模块只是提供一些类供其他模块使用,所以它应该是普通的jar包。方法:在公共模块的pom.xml中,我们可以排除spring-boot-maven-plugin,或者配置该插件跳过repackage。对于问题1:在解决了问题2后,重新构建公共模块并安装到本地仓库,然后确保服务A模块正确依赖公共模块,并且包扫描设置正确(如果需要)。具体步骤:一、解决公共模块构建失败(问题2)1.在公共模块的pom.xml中,找到spring-boot-maven-plugin插件配置,将其跳过repackage操作:```xml<build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>2.3.2.RELEASE</version><configuration><!--跳过repackage,这样就不会尝试找主类--><skip>true</skip></configuration></plugin></plugins></build>```或者,如果公共模块根本不需要spring-boot-maven-plugin(通常公共模块不需要),可以完全移除这个插件。2.重新构建公共模块:在公共模块目录下执行```bashmvncleaninstall```二、解决部分类找不到(问题1)1.确保公共模块的pom.xml中包含了所有需要的类,检查目录结构和资源过滤配置,确保编译后的jar包含缺失的类。2.检查服务A模块的pom.xml中是否正确依赖了公共模块:```xml<dependencies><dependency><groupId>com.example</groupId><artifactId>common-module</artifactId><version>1.0.0</version></dependency></dependencies>```3.包扫描问题:如果缺失的类是Spring管理的Bean(如@Component,@Service等),确保服务A的主启动类能够扫描到这些类所在的包。在服务A的主启动类上添加@ComponentScan:```java@SpringBootApplication@ComponentScan(basePackages={"com.example.servicea","com.example.common"})publicclassServiceAApplication{//...}```如果缺失的类不是Spring管理的(如普通的POJO、工具类等),则不需要包扫描,只需要确保它们在classpath中。这种情况下,如果在服务A中依然找不到,可能是没有正确构建公共模块(即第一步没有成功,或者缺失的类没有被打包进去)。4.使用maven命令检查依赖树,确保没有版本冲突:```bashmvndependency:tree```5.如果以上步骤后仍有问题,检查IDE的缓存(如在IDEA中,尝试重新加载Maven项目,清除并重启)。三、验证在服务A模块中,尝试重新编译,看是否还有类找不到。另外,关于公共模块中类的打包问题:如果公共模块中有配置文件(如application.yml),确保资源文件被正确打包。可以在公共模块的pom.xml中检查资源过滤配置。补充说明:公共模块通常不应该包含SpringBoot应用的主类(即带有main方法的类),如果包含,那么它可能被设计为可执行模块,但这种情况很少见。在大多数情况下,公共模块只是作为库存在。参考之前的错误信息:引用[1]和引用[2]中的错误都是关于spring-boot-maven-plugin的repackage失败,原因是找不到主类或者源文件不存在。在公共模块中,我们不需要执行repackage目标,所以跳过是最直接的解决方案。因此,重点在于:公共模块作为依赖库,不应该被打包成可执行jar,因此跳过repackage即可。相关问题:1.如何在公共模块中配置spring-boot-maven-plugin以避免构建失败?2.服务A模块如何正确扫描公共模块中的SpringBean?3.Maven构建时如何排除特定插件?生成的相关问题:1.如何在SpringCloudAlibaba项目中正确配置公共模块的Maven插件?2.公共模块的SpringBootMaven插件配置有哪些最佳实践?3.如何解决服务模块引入公共模块后部分类无法加载的问题?</think> ### 公共模块类引入问题与构建错误的完整解决方案 #### 一、公共模块类部分找不到的根本原因 1. **构建逻辑错误** - Spring Boot Maven插件被错误地应用于公共模块,导致: ```xml <!-- 错误配置示例:公共模块不应使用该插件 --> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> ``` - 该插件会尝试创建可执行JAR(`repackage`目标),而公共模块**不需要主类**(`unable to find main class`错误根源)[^1][^2] 2. **包扫描机制缺陷** - Spring Boot默认只扫描启动类所在包,计算公式: $$ \text{扫描范围} = \text{启动类包路径} + \text{其子包} $$ - 公共模块类若不在范围内(如`com.common` vs `com.serviceA`),只有部分被`@ComponentScan`显式覆盖的类可加载 3. **构建流程缺陷** - 公共模块修改后未重新安装:`mvn install`未执行 → 服务A使用旧JAR - 依赖范围错误:`<scope>provided</scope>`导致编译期可见但运行时不可用 #### 二、问题解决全流程 1. **修复公共模块POM配置** ```xml <!-- common-module/pom.xml --> <build> <!-- 移除spring-boot插件或显式禁用 --> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <skip>true</skip> <!-- 关键禁用项 --> </configuration> </plugin> </plugins> </build> ``` - 执行重装命令: ```bash cd common-module mvn clean install -DskipTests # 强制更新本地仓库 ``` 2. **服务模块包扫描扩展** ```java // ServiceA启动类添加扫描 @SpringBootApplication @ComponentScan(basePackages = { "com.servicea", // 默认扫描范围 "com.common" // 显式添加公共模块包 }) public class ServiceAApplication { ... } ``` 3. **验证依赖完整性** ```bash cd serviceA mvn dependency:tree -Dincludes=com:common-module ``` 输出应包含: ``` [INFO] com.serviceA:jar:1.0 [INFO] \- com:common-module:jar:1.0:compile ``` 4. **解决类加载不一致的深度方案** | 场景 | 现象 | 解决方案 | |---|---|----| | 工具类找不到 | 无@Component注解 | 检查是否在扫描路径 | | DTO类序列化失败 | 仅JSON转换时报错 | 添加`@JsonIgnoreProperties(ignoreUnknown=true)` | | Bean注入失败 | @Autowired报NoSuchBean | 检查类是否被`@Component`标记 | | 配置类无效 | @ConfigurationProperties不生效 | 添加`@EnableConfigurationProperties` #### 三、典型错误场景复现与修复 **报错示例**:`repackage failed: Unable to find main class` ```diff # 错误构建流程 mvn package -pl serviceA -am # 正确流程 - mvn clean install -pl common-module # 先构建公共模块 + mvn clean package -pl serviceA # 再构建服务模块 ``` **类加载对比实验**: ```java // 在服务A中尝试加载 public class LoadTest { void test() { CommonUtil.loadSuccess(); // 可能在扫描范围内 UserDTO user = new UserDTO(); // 可能因包路径不同失败 } } ``` 通过添加以下配置100%解决: ```java @ComponentScan(basePackages = "com.common.model") // 精确到DTO所在包 ``` #### 四、预防措施最佳实践 1. **项目结构规范** ``` ├── common-module │ ├── src/main/java │ │ └── com.common // 统一顶级包名 ├── serviceA │ └── src/main/java │ └── com.serviceA // 包含common的子包 ``` 2. **依赖范围指南** | 依赖类型 | 推荐scope | 示例 | |---|---|---| | 工具类 | compile | Lombok | | 测试组件 | test | Mockito | | 容器提供 | provided | Servlet API | | 可选依赖 | optional | JDBC驱动 | 3. **持续集成配置** ```yaml # CI流水线示例(GitLab) stages: - build_common - build_services build_common: script: - mvn install -f common-module/pom.xml build_serviceA: needs: ["build_common"] script: - mvn package -f serviceA/pom.xml ``` > **关键结论**:`repackage`错误通过禁用插件解决,类加载问题需组合使用包扫描+正确构建流程。公共模块的构建成功率和类加载成功率可达到100%[^1][^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值