SpringBoot多模块自动配置失效问题的解决方案
目录
- 一、问题背景与场景
- 1.1 场景描述
- 1.2 核心问题
- 二、解决方案
- 2.1 步骤1:声明自动配置类
- 2.2 步骤2:确保全局异常处理器生效
- 2.3 步骤3:检查依赖传递与冲突
- 2.4 步骤4:确保包扫描路径正确
- 2.5 步骤5:验证条件注解
- 2.6 步骤6:IDEA路径问题排查
- 三、核心知识点详解
- 3.1 Spring Boot自动配置机制
- 3.2 依赖管理
- 3.3 条件注解进阶用法
- 3.4 多模块包扫描
- 四、常见陷阱与解决方案
- 4.1 陷阱1:IDEA路径错误
- 4.2 陷阱2:配置文件覆盖
- 4.3 陷阱3:未激活Profile
- 4.4 陷阱4:Spring Boot 3.x兼容性问题
- 五、验证配置生效的方法
- 5.1 启动日志检查
- 5.2 Bean注入验证
- 5.3 跨域配置测试
- 5.4 异常处理器验证
- 六、完整解决方案代码示例
- 6.1 模块A的POM配置
- 6.2 模块B的POM配置
- 6.3 模块B的启动类
- 6.4 模块A的自动配置文件
- 七、总结与最佳实践(代码视角)
- 7.1 核心总结
- 7.2 最佳实践代码模板
- 八、附录:工具与命令
- 8.1 依赖树分析
- 8.2 日志级别调试
- 8.3 模块间依赖验证
- 九、补充
- 1. @AutoConfiguration注解详解
- 1.1 基本概念
- 1.2 @AutoConfiguration与@Configuration的区别
- 1.3 @AutoConfiguration的使用场景
- 场景2:替代旧版spring.factories
- 2. @Bean注解详解
- 2.1 基本概念
- 2.2 @Bean的使用场景
- 3. @Configuration与@Bean的协作关系
- 3.1 基础配置类结构
- 4. 为什么必须使用@AutoConfiguration?能否用@Configuration替代?
- 4.1 必须使用@AutoConfiguration的情况
- 4.2 @Configuration的替代方案
- 5. 示例代码中的关键注解解析
- 5.1 ResourcesConfig示例
- 5.2 全局异常处理器示例
- 6. 常见问题与解答
- 7. 完整自动配置类代码示例
- 8. 关键配置文件说明
- 8.1 AutoConfiguration.imports文件
- 8.2 spring.factories(Spring Boot 2.x兼容)
一、问题背景与场景
1.1 场景描述
假设存在两个模块:
- 模块A:提供通用配置(如跨域配置、全局异常处理、拦截器)。
- 模块B:引用模块A,但模块A的配置未生效(如跨域配置无效、异常处理器未捕获异常)。
1.2 核心问题
- 自动配置类未被加载:模块A的
@AutoConfiguration
类未在模块B中生效。 - 依赖冲突:第三方库间接引入了与模块A冲突的依赖(如日志框架版本不一致)。
- 条件注解限制:配置类因
@ConditionalOnClass
等条件未满足而跳过。 - 包扫描路径错误:模块B未扫描到模块A的包路径。
二、解决方案
2.1 步骤1:声明自动配置类
2.1.1 使用META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
在模块A的src/main/resources
目录下创建以下路径:
src/main/resources/ └── META-INF/ └── spring/ └── org.springframework.boot.autoconfigure.AutoConfiguration.imports
文件内容为一行一个自动配置类的全限定名:
com.example.moduleA.config.ResourcesConfig
2.1.2 代码示例:自动配置类
// 模块A的ResourcesConfig.Java @AutoConfiguration @ConditionalOnWebApplication(type = Type.SERVLET) // 仅在Servlet环境生效 public class ResourcesConfig implements WebMvcConfigurer { @Override public void addInterceptors(InterceptorRegistry registry) { // 全局性能拦截器 registry.addInterceptor(new PlusWebInvokeTimeInterceptor()) .addPathPatterns("/**") // 拦截所有路径 .excludePathPatterns("/actuator/**"); // 排除监控端点 } @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { // 静态资源处理(如Swagger) registry.addResourceHandler("/docs/**") .addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/"); } /** * 跨域配置(通过@Bean注册) */ @Bean public CorsFilter corsFilter() { CorsConfiguration config = new CorsConfiguration(); config.setAllowCredentials(true); config.addAllowedOriginPattern("*"); // 允许所有源 config.addAllowedHeader("*"); // 允许所有请求头 config.addAllowedMethod("*"); // 允许所有HTTP方法 config.setMaxAge(1800L); // 预检请求缓存时间 UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", config); return new CorsFilter(source); } }
2.2 步骤2:确保全局异常处理器生效
2.2.1 全局异常处理器代码
// 模块A的GlobalExceptionHandler.java @Slf4j @RestControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(HttpRequestMethodNotSupportedException.class) public ResponseEntity<String> handleHttpRequestMethodNotSupported( HttpRequestMethodNotSupportedException e, HttpServletRequest request) { log.error("请求地址'{}', 不支持'{}'请求", request.getRequestURI(), e.getMethod()); return ResponseEntity.status(HttpStatus.METHOD_NOT_ALLOWED) .body("请求方法不支持: " + e.getMethod()); } @ExceptionHandler(ServiceException.class) public ResponseEntity<ErrorResponse> handleServiceException( ServiceException e, HttpServletRequest request) { log.error("业务异常: {}", e.getMessage()); return ResponseEntity.status(e.getStatusCode()) .body(new ErrorResponse(e.getCode(), e.getMessage())); } @ExceptionHandler(Exception.class) public ResponseEntity<String> handleGlobalException(Exception e) { log.error("全局异常: {}", e.getMessage(), e); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) .body("系统内部错误"); } private static class ErrorResponse { private final int code; private final String message; public ErrorResponse(int code, String message) { this.code = code; this.message = message; } } }
2.3 步骤3:检查依赖传递与冲突
2.3.1 排除间接依赖冲突
假设模块B引用了myBATis-spring-boot-starter
,而该依赖间接引入了spring-boot-starter-logging
(导致日志框架冲突)。需在POM中排除:
<!-- 模块B的pom.XML --> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>3.0.1</version> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> </exclusions> </dependency>
2.3.2 检查依赖树
使用Maven或Gradle命令查看依赖树:
# Maven mvn dependency:tree | grep -i logback # Gradle ./gradlew dependencies --configuration compileClasspath
2.4 步骤4:确保包扫描路径正确
2.4.1 显式指定扫描路径
在模块B的启动类中设置scanBasePackages
:
// 模块B的启动类 @SpringBootApplication( scanBasePackages = { "com.example.moduleA.config", "com.example.moduleA.handler", "com.example.moduleB.controller" } ) public class ModuleBApplication { public static void main(String[] args) { SpringApplication applic编程客栈ation = new SpringApplication(ModuleBApplication.class); application.setAdditionalProfiles("dev"); // 激活开发环境配置 application.run(args); } }
2.4.2 包结构优化
确保模块A的包路径是模块B启动类的子包:
com.example ├── moduleA │ ├── config │ │ └── ResourcesConfig.java │ └── handler │ └── GlobalExceptionHandler.java └── moduleB ├── controller │ └── UserController.java └── ModuleBApplication.java
2.5 步骤5:验证条件注解
2.5.1 示例:基于属性的条件
// 模块A的FeatureAutoConfiguration.java @Configuration @ConditionalOnProperty(name = "feature.enabled", havingValue = "true") public class FeatureAutoConfiguration { @Bean public FeatureService featureService() { return new FeatureServiceImpl(); } }
在application.yml
中激活条件:
feature: enabled: true
2.6 步骤6:IDEA路径问题排查
2.6.1 确保目录结构正确
- 错误路径:IDEA可能将
META-INF/spring
显示为META-INF.spring
。 - 解决方法:
- 删除错误路径。
- 右键
src/main/resources
→ New → Directory → 输入META-INF/spring
。 - 创建
AutoConfiguration.imports
文件。
三、核心知识点详解
3.1 Spring Boot自动配置机制
3.1.1 核心组件
- 条件注解:
@ConditionalOnClass
:类路径存在指定类时生效。@ConditionalOnMissingBean
:容器中无指定Bean时生效。@ConditionalOnProperty
:属性存在且符合条件时生效。@ConditionalOnWebApplication
:仅在Web环境生效。
- 自动配置类:
- 通过
@AutoConfiguration
标注,配合AutoConfiguration.imports
文件声明。
- 通过
- 加载流程:
- Spring Boot 2.x:通过
spring.factories
文件加载自动配置类。 - Spring Boot 3.x:推荐使用
AutoConfiguration.imports
。
- Spring Boot 2.x:通过
3.1.2 新旧机制对比
特性 | spring.factories(旧) | AutoConfiguration.imports(新) |
---|---|---|
文件路径 | META-INF/spring.factories | META-INF/spring/org...AutoConfiguration.imports |
格式 | 需声明EnableAutoConfiguration键 | 直接列出类名,无需键值对 |
性能 | 全局扫描,可能加载冗余配置 | 按需加载,性能更优 |
3.2 依赖管理
3.2.1 排除依赖冲突
<!-- 模块B的pom.xml --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <编程;artifactId>spring-boot-starter-logging</artifactId> </exclusion> </exclusions> </dependency>
3.2.2 引入必要依赖
<!-- 引入log4j2 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-log4j2</artifactId> </dependency>
3.3 条件注解进阶用法
3.3.1 组合条件
@Configuration @ConditionalOnClass(RedisClient.class) // 类路径存在RedisClient @ConditionalOnProperty(name = "redis.enabled", matchIfMissing = true) // 属性存在或未配置时生效 public class RedisAutoConfig { // 配置逻辑 }
3.3.2 优先级控制
@AutoConfiguration(after = AnotherConfig.class) public class MyConfig { // 该配置类将在AnotherConfig之后加载 }
3.4 多模块包扫描
3.4.1 动态扫描策略
// 使用@Import动态导入配置类 @Import({DatabaseAutoConfiguration.class, LoggingAutoConfiguration.class}) public class ModuleBApplication { // ... }
四、常见陷阱与解决方案
4.1 陷阱1:IDEA路径错误
- 现象:
META-INF/spring
目录被错误显示为META-INF.spring
。 - 解决:
- 删除错误路径。
- 右键
src/main/resources
→ New → Directory → 输入META-INF/spring
。 - 重新创建
AutoConfiguration.imports
文件。
4.2 陷阱2:配置文件覆盖
- 现象:模块B的
application.yml
覆盖模块A的配置。 - 解决:
- 将模块A的配置文件放置在
src/main/resources/config/
目录下。 - 在模块B中指定激活配置文件:
- 将模块A的配置文件放置在
4.3 陷阱3:未激活Profile
- 现象:环境特定配置未生效。
- 解决:
# 启动时指定Profile java -jar app.jar --spring.profiles.active=dev
4.4 陷阱4:Spring Boot 3.x兼容性问题
- 现象:
spring.factories
配置失效。 - 解决:
将配置迁移到新路径:
# 模块A的META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports com.example.moduleA.config.ResourcesConfig com.example.moduleA.handler.GlobalExceptionHandler
五、验证配置生效的方法
5.1 启动日志检查
- 日志级别:
logging.level.root=DEBUG
- 关键日志:
Positive matches: - ResourcesConfig (com.example.moduleA.config.ResourcesConfig) - GlobalExceptionHandler (com.example.moduleA.handler.GlobalExceptionHandler)
5.2 Bean注入验证
// 模块B的测试类 @RestController public class HealthCheckController { @Autowired private CorsFilter corsFilter; @GetMapping("/health/cors") public String health() { return "CorsFilter: " + corsFilter.getClass().getName(); } }
5.3 跨域配置测试
5.3.1 测试步骤
- 发送带有
Origin
头的请求:
curl -H "Origin: https://test.com" -X GET http://localhost:8080/api/test
预期响应头:
Access-Control-Allow-Origin: * Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
5.4 异常处理器验证
5.4.1 测试业务异常
// 模块B的Controller @RestController public class TestController { @GetMapping("/test") public ResponseEntity<String> test() { throw new ServiceException("自定义异常", HttpStatus.BAD_REQUEST); } }
预期响应:
{ "code": 400, "message": "自定义异常" }
六、完整解决方案代码示例
6.1 模块A的POM配置
<!-- 模块A的pom.xml --> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> </dependencies>
6.2 模块B的POM配置
<!-- 模块B的pom.xml --> <dependencies> <dependency> <groupId>com.example</groupId> <artifactId>moduleA</artifactId> <version>1.0.0</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies>
6.3 模块B的启动类
// 模块B的启动类 @SpringBootApplication( scanBasePackages = { "com.example.moduleA.config", "com.example.moduleA.handler", "com.example.moduleB.controller" } ) public class ModuleBApplication { public static void main(String[] args) { SpringApplication application = new SpringApplication(ModuleBApplication.class); application.setAdditionalProfiles("dev"); // 激活开发环境配置 application.run(args); } }
6.4 模块A的自动配置文件
# 模块A的META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports com.example.moduleA.config.ResourcesConfig com.example.moduleA.handler.GlobalExceptionHandler
七、总结与最佳实践(代码视角)
7.1 核心总结
- 自动配置类必须通过
AutoConfiguration.imports
显式声明:- 例如:在模块A的
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
中列出所有自动配置类。
- 例如:在模块A的
- Bean注册需通过
@Bean
或实现WebMvcConfigurer
:- 如
CorsFilter
通过@Bean
注册,WebMvcConfigurer
方法需在@AutoConfiguration
类中实现。
- 如
- 包扫描路径必须覆盖所有模块:
- 模块B的启动类需显式扫描模块A的包路径。
7.2 最佳实践代码模板
7.2.1 模块A的自动配置类模板
@AutoConfiguration @ConditionalOnClass(DispatcherServlet.class) // 依赖Servlet环境 public class ResourcesConfig implements WebMvcConfigurer { // 跨域、拦截器等配置 @Bean public GlobalExceptionHandler globalExceptionHandler() { return new GlobalExceptionHandler(); // 手动注册异常处理器 } }
7.2.2 全局异常处理器模板
@Slf4j @RestControllerAdvice(basePackages = {"com.example.moduleA", "com.example.moduleB"}) public class GlobalExceptionHandler { @ExceptionHandler(Exception.class) public ResponseEntity<String> handleGlobalException(Exception e) { log.error("全局异常: {}", e.getMessage(), e); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR) .body("系统内部错误"); } }
八、附录:工具与命令
8.1 依赖树分析
mvn dependency:tree
8.2 日志级别调试
java -jar app.jar --logging.level.root=DEBUG
8.3 模块间依赖验证
# Gradle检查依赖冲突 ./gradlew dependencies --configuration compileClasspath
九、补充
1. @AutoConfiguration注解详解
1.1 基本概念
- 定义:
@AutoConfiguration
是Spring Boot 3.x引入的注解,用于标记一个类为自动配置类,其作用是简化自动配置类的声明,无需在META-INF/spring.factories
中手动注册。 - 作用:
- 自动注册到Spring容器:被
@AutoConfiguration
标注的类会被Spring Boot自动识别为自动配置类。 - 按需加载:结合条件注解(如
@ConditionalOnClass
),仅在满足条件时生效。 - 模块化配置:适用于多模块项目,将配置逻辑封装到独立模块中。
- 自动注册到Spring容器:被
1.2 @AutoConfiguration与@Configuration的区别
特性 | @AutoConfiguration | @Configuration |
---|---|---|
作用 | 自动配置类,无需手动注册 | 普通配置类,需通过其他方式注册 |
自动注册 | 自动注册到Spring容器(需配合AutoConfiguration.imports) | 需显式注册(如通过组件扫描或@Import) |
适用场景 | 自动配置场景(如多模块共享配置) | 通用配置类(如自定义Bean) |
是否需要额外配置 | 需在AutoConfiguration.imports文件中声明 | 无需额外配置(但需被Spring容器扫描) |
依赖关系 | 通常与@Conditional注解结合 | 可独立使用,但需手动管理Bean依赖 |
1.3 @AutoConfiguration的使用场景
场景1:多模块共享配置
// 模块A的ResourcesConfig.java @AutoConfiguration @ConditionalOnWebApplication(type = Type.SERVLET) public class ResourcesConfig implements WebMvcConfigurer { // 跨域配置、拦截器等 }
- 关键点:
- 通过
@AutoConfiguration
标记为自动配置类。 - 在模块A的
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
文件中声明该类。 - 模块B引用模块A后,无需手动导入,Spring Boot会自动加载。
- 通过
场景2:替代旧版spring.factories
# Spring Boot 2.x的spring.factories(需手动注册) org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.example.moduleA.config.ResourcesConfig,\ com.example.moduleA.handler.GlobalExceptionHandler
- Spring Boot 3.x的改进:使用
@AutoConfiguration
+AutoConfiguration.imports
文件,无需维护冗长的spring.factories。
2. @Bean注解详解
2.1 基本概念
- 定义:
@Bean
是Spring框架的核心注解,用于将方法返回的对象注册为Spring容器管理的Bean。 - 作用:
- 显式声明Bean:开发者通过方法定义Bean的创建逻辑。
- 依赖注入:方法参数支持依赖注入(如
@Autowired
)。 - 灵活控制:可指定Bean作用域、初始化方法、条件等。
- 作用域控制:通过@Scope指定Bean的作用域(如singleton、prototype)。
2.2 @Bean的使用场景
场景1:定义基础Bean
@Configuration public class DataSourceConfig { @Bean @ConditionalOnMissingBean(DataSource.class) // 仅当容器中没有DataSource时生效 public DataSource dataSource() { HikariDataSource ds = new HikariDataSource(); ds.setJdbcUrl("jdbc:mysql://localhost:3306/test"); return ds; } }
- 关键点:
- 通过
@Bean
将dataSource()
方法返回的HikariDataSource
注册为Bean。 - 结合
@ConditionalOnMissingBean
避免与用户自定义Bean冲突。
- 通过
场景2:注册第三方库Bean
@Configuration public class jsonConfig { @Bean public ObjectMapper objectMapper() { ObjectMapper mapper = new ObjectMapper(); mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd")); return mapper; } }
- 关键点:
- 将第三方库的
ObjectMapper
注册为Spring Bean,方便全局使用。
- 将第三方库的
场景3:作用域控制
@Bean @Scope("prototype") // 每次请求创建新实例 public MyPrototypeBean prototypeBeaphpn() { return new MyPrototypeBean(); }
3. @Configuration与@Bean的协作关系
3.1 基础配置类结构
@Configuration // 标记为配置类 public class MyAutoConfiguration { @Bean // 定义Bean public MyService myService() { return new MyServiceImpl(); } }
- 关键点:
@Configuration
是配置类的“身份标识”。@Bean
是配置类中定义Bean的“工具”。
4. 为什么必须使用@AutoConfiguration?能否用@Configuration替代?
4.1 必须使用@AutoConfiguration的情况
- 场景:在多模块项目中,模块A的配置需被模块B自动加载。
- 原因:
@AutoConfiguration
配合AutoConfiguration.imports
文件,无需手动注册。- 如果仅用
@Configuration
,需通过以下方式显式加载:- 在模块B的启动类中指定扫描路径。
- 通过
@Import(ResourcesConfig.class)
导入。 - 在
spring.factories
中注册(Spring Boot 2.x方式)。
- 结论:在Spring Boot 3.x中,
@AutoConfiguration
是更简洁的解决方案。
4.2 @Configuration的替代方案
// 方案1:在模块B启动类中显式扫描模块A的包 @SpringBootApplication(scanBasePackages = {"com.example.moduleA", "com.example.moduleB"}) public class ModuleBApplication { ... } // 方案2:使用@Import导入配置类 @Configuration @Import(ResourcesConfig.class) public class ModuleBConfig { ... }
- 缺点:
- 需手动维护包路径或导入关系,耦合性更高。
- 不具备条件化加载能力(除非手动添加
@Conditional
注解)。
5. 示例代码中的关键注解解析
5.1 ResourcesConfig示例
@AutoConfiguration @ConditionalOnWebApplication(type = Type.SERVLET) public class ResourcesConfig implements WebMvcConfigurer { @Bean public CorsFilter corsFilter() { ... } @Override public void addInterceptors(InterceptorRegistry registry) { ... } }
- 关键点:
- @AutoConfiguration:声明为自动配置类。
- @ConditionalOnWebApplication:仅在Servlet环境生效。
- @Bean:将
CorsFilter
注册为Bean。 - 实现WebMvcConfigurer:通过继承接口直接扩展Spring MVC配置。
5.2 全局异常处理器示例
@RestContr编程ollerAdvice public class GlobalExceptionHandler { @ExceptionHandler(Exception.class) public ResponseEntity<String> handleGlobalException(Exception e) { ... } }
- 关键点:
@RestControllerAdvice
:标记为全局异常处理类。- 无需
@Bean
,因为Spring通过组件扫描自动识别。
6. 常见问题与解答
Q1:为什么我的自动配置类未被加载?
- 可能原因:
- 未在
AutoConfiguration.imports
文件中声明类。 - 依赖未正确引入(如模块B未依赖模块A)。
- 条件注解未满足(如
@ConditionalOnClass
的类不存在)。
- 未在
- 解决方案:
- 检查
AutoConfiguration.imports
文件路径是否正确。 - 确保模块编程客栈B的POM中包含模块A的依赖。
- 在启动日志中搜索
Positive matches
,确认条件是否满足。
- 检查
Q2:@Bean和@Component的区别?
注解 | 作用范围 | 使用场景 |
---|---|---|
@Bean | 方法级 | 在配置类中定义Bean的创建逻辑 |
@Component | 类级 | 通过组件扫描自动注册Bean |
Q3:为什么自动配置类需要实现WebMvcConfigurer?
- 原因:Spring MVC的扩展机制允许通过实现
WebMvcConfigurer
接口或使用@Bean
注册WebMvcConfigurer
来添加拦截器、跨域配置等。 - 示例:
@Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new MyInterceptor()); }
7. 完整自动配置类代码示例
// 模块A的ResourcesConfig.java @AutoConfiguration @ConditionalOnWebApplication(type = Type.SERVLET) public class ResourcesConfig implements WebMvcConfigurer { @Bean public CorsFilter corsFilter() { CorsConfiguration config = new CorsConfiguration(); config.addAllowedOriginPattern("*"); config.addAllowedMethod("*"); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", config); return new CorsFilter(source); } @Bean public MyInterceptor myInterceptor() { return new MyInterceptor(); } @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(myInterceptor()) .addPathPatterns("/**"); } @Bean @ConditionalOnMissingBean public MyService myService() { return new MyServiceImpl(); } }
8. 关键配置文件说明
8.1 AutoConfiguration.imports文件
# 模块A的META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports com.example.moduleA.config.ResourcesConfig
- 作用:告知Spring Boot哪些类是自动配置类,无需手动注册到spring.factories。
8.2 spring.factories(Spring Boot 2.x兼容)
# 模块A的META-INF/spring.factories org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.example.moduleA.config.ResourcesConfig,\ com.example.moduleA.handler.GlobalExceptionHandler
- 兼容性说明:Spring Boot 3.x支持同时使用两种方式,但推荐使用
@AutoConfiguration
。
以上就是SpringBoot多模块自动配置失效问题的解决方案的详细内容,更多关于SpringBoot多模块自动配置失效的资料请关注编程客栈(www.devze.com)其它相关文章!
精彩评论