SpringBoot多模塊自動(dòng)配置失效問(wèn)題的解決方案
一、問(wèn)題背景與場(chǎng)景
1.1 場(chǎng)景描述
假設(shè)存在兩個(gè)模塊:
- 模塊A:提供通用配置(如跨域配置、全局異常處理、攔截器)。
- 模塊B:引用模塊A,但模塊A的配置未生效(如跨域配置無(wú)效、異常處理器未捕獲異常)。
1.2 核心問(wèn)題
- 自動(dòng)配置類未被加載:模塊A的
@AutoConfiguration類未在模塊B中生效。 - 依賴沖突:第三方庫(kù)間接引入了與模塊A沖突的依賴(如日志框架版本不一致)。
- 條件注解限制:配置類因
@ConditionalOnClass等條件未滿足而跳過(guò)。 - 包掃描路徑錯(cuò)誤:模塊B未掃描到模塊A的包路徑。
二、解決方案
2.1 步驟1:聲明自動(dòng)配置類
2.1.1 使用META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
在模塊A的src/main/resources目錄下創(chuàng)建以下路徑:
src/main/resources/
└── META-INF/
└── spring/
└── org.springframework.boot.autoconfigure.AutoConfiguration.imports
文件內(nèi)容為一行一個(gè)自動(dòng)配置類的全限定名:
com.example.moduleA.config.ResourcesConfig
2.1.2 代碼示例:自動(dòng)配置類
// 模塊A的ResourcesConfig.java
@AutoConfiguration
@ConditionalOnWebApplication(type = Type.SERVLET) // 僅在Servlet環(huán)境生效
public class ResourcesConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 全局性能攔截器
registry.addInterceptor(new PlusWebInvokeTimeInterceptor())
.addPathPatterns("/**") // 攔截所有路徑
.excludePathPatterns("/actuator/**"); // 排除監(jiān)控端點(diǎn)
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// 靜態(tài)資源處理(如Swagger)
registry.addResourceHandler("/docs/**")
.addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/");
}
/**
* 跨域配置(通過(guò)@Bean注冊(cè))
*/
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOriginPattern("*"); // 允許所有源
config.addAllowedHeader("*"); // 允許所有請(qǐng)求頭
config.addAllowedMethod("*"); // 允許所有HTTP方法
config.setMaxAge(1800L); // 預(yù)檢請(qǐng)求緩存時(shí)間
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("請(qǐng)求地址'{}', 不支持'{}'請(qǐng)求", request.getRequestURI(), e.getMethod());
return ResponseEntity.status(HttpStatus.METHOD_NOT_ALLOWED)
.body("請(qǐng)求方法不支持: " + e.getMethod());
}
@ExceptionHandler(ServiceException.class)
public ResponseEntity<ErrorResponse> handleServiceException(
ServiceException e, HttpServletRequest request) {
log.error("業(yè)務(wù)異常: {}", 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("系統(tǒng)內(nèi)部錯(cuò)誤");
}
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 排除間接依賴沖突
假設(shè)模塊B引用了mybatis-spring-boot-starter,而該依賴間接引入了spring-boot-starter-logging(導(dǎo)致日志框架沖突)。需在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 檢查依賴樹(shù)
使用Maven或Gradle命令查看依賴樹(shù):
# Maven mvn dependency:tree | grep -i logback # Gradle ./gradlew dependencies --configuration compileClasspath
2.4 步驟4:確保包掃描路徑正確
2.4.1 顯式指定掃描路徑
在模塊B的啟動(dòng)類中設(shè)置scanBasePackages:
// 模塊B的啟動(dòng)類
@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"); // 激活開(kāi)發(fā)環(huán)境配置
application.run(args);
}
}
2.4.2 包結(jié)構(gòu)優(yōu)化
確保模塊A的包路徑是模塊B啟動(dòng)類的子包:
com.example
├── moduleA
│ ├── config
│ │ └── ResourcesConfig.java
│ └── handler
│ └── GlobalExceptionHandler.java
└── moduleB
├── controller
│ └── UserController.java
└── ModuleBApplication.java
2.5 步驟5:驗(yàn)證條件注解
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路徑問(wèn)題排查
2.6.1 確保目錄結(jié)構(gòu)正確
- 錯(cuò)誤路徑:IDEA可能將
META-INF/spring顯示為META-INF.spring。 - 解決方法:
- 刪除錯(cuò)誤路徑。
- 右鍵
src/main/resources→ New → Directory → 輸入META-INF/spring。 - 創(chuàng)建
AutoConfiguration.imports文件。
三、核心知識(shí)點(diǎn)詳解
3.1 Spring Boot自動(dòng)配置機(jī)制
3.1.1 核心組件
- 條件注解:
@ConditionalOnClass:類路徑存在指定類時(shí)生效。@ConditionalOnMissingBean:容器中無(wú)指定Bean時(shí)生效。@ConditionalOnProperty:屬性存在且符合條件時(shí)生效。@ConditionalOnWebApplication:僅在Web環(huán)境生效。
- 自動(dòng)配置類:
- 通過(guò)
@AutoConfiguration標(biāo)注,配合AutoConfiguration.imports文件聲明。
- 通過(guò)
- 加載流程:
- Spring Boot 2.x:通過(guò)
spring.factories文件加載自動(dòng)配置類。 - Spring Boot 3.x:推薦使用
AutoConfiguration.imports。
- Spring Boot 2.x:通過(guò)
3.1.2 新舊機(jī)制對(duì)比
| 特性 | spring.factories(舊) | AutoConfiguration.imports(新) |
|---|---|---|
| 文件路徑 | META-INF/spring.factories | META-INF/spring/org...AutoConfiguration.imports |
| 格式 | 需聲明EnableAutoConfiguration鍵 | 直接列出類名,無(wú)需鍵值對(duì) |
| 性能 | 全局掃描,可能加載冗余配置 | 按需加載,性能更優(yōu) |
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 條件注解進(jìn)階用法
3.3.1 組合條件
@Configuration
@ConditionalOnClass(RedisClient.class) // 類路徑存在RedisClient
@ConditionalOnProperty(name = "redis.enabled", matchIfMissing = true) // 屬性存在或未配置時(shí)生效
public class RedisAutoConfig {
// 配置邏輯
}
3.3.2 優(yōu)先級(jí)控制
@AutoConfiguration(after = AnotherConfig.class)
public class MyConfig {
// 該配置類將在AnotherConfig之后加載
}
3.4 多模塊包掃描
3.4.1 動(dòng)態(tài)掃描策略
// 使用@Import動(dòng)態(tài)導(dǎo)入配置類
@Import({DatabaseAutoConfiguration.class, LoggingAutoConfiguration.class})
public class ModuleBApplication {
// ...
}
四、常見(jiàn)陷阱與解決方案
4.1 陷阱1:IDEA路徑錯(cuò)誤
- 現(xiàn)象:
META-INF/spring目錄被錯(cuò)誤顯示為META-INF.spring。 - 解決:
- 刪除錯(cuò)誤路徑。
- 右鍵
src/main/resources→ New → Directory → 輸入META-INF/spring。 - 重新創(chuàng)建
AutoConfiguration.imports文件。
4.2 陷阱2:配置文件覆蓋
- 現(xiàn)象:模塊B的
application.yml覆蓋模塊A的配置。 - 解決:
- 將模塊A的配置文件放置在
src/main/resources/config/目錄下。 - 在模塊B中指定激活配置文件:
- 將模塊A的配置文件放置在
4.3 陷阱3:未激活Profile
- 現(xiàn)象:環(huán)境特定配置未生效。
- 解決:
# 啟動(dòng)時(shí)指定Profile java -jar app.jar --spring.profiles.active=dev
4.4 陷阱4:Spring Boot 3.x兼容性問(wèn)題
- 現(xiàn)象:
spring.factories配置失效。 - 解決:
將配置遷移到新路徑:
# 模塊A的META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports com.example.moduleA.config.ResourcesConfig com.example.moduleA.handler.GlobalExceptionHandler
五、驗(yàn)證配置生效的方法
5.1 啟動(dòng)日志檢查
- 日志級(jí)別:
logging.level.root=DEBUG
- 關(guān)鍵日志:
Positive matches: - ResourcesConfig (com.example.moduleA.config.ResourcesConfig) - GlobalExceptionHandler (com.example.moduleA.handler.GlobalExceptionHandler)
5.2 Bean注入驗(yàn)證
// 模塊B的測(cè)試類
@RestController
public class HealthCheckController {
@Autowired
private CorsFilter corsFilter;
@GetMapping("/health/cors")
public String health() {
return "CorsFilter: " + corsFilter.getClass().getName();
}
}
5.3 跨域配置測(cè)試
5.3.1 測(cè)試步驟
- 發(fā)送帶有
Origin頭的請(qǐng)求:
curl -H "Origin: https://test.com" -X GET http://localhost:8080/api/test
預(yù)期響應(yīng)頭:
Access-Control-Allow-Origin: * Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
5.4 異常處理器驗(yàn)證
5.4.1 測(cè)試業(yè)務(wù)異常
// 模塊B的Controller
@RestController
public class TestController {
@GetMapping("/test")
public ResponseEntity<String> test() {
throw new ServiceException("自定義異常", HttpStatus.BAD_REQUEST);
}
}
預(yù)期響應(yīng):
{
"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的啟動(dòng)類
// 模塊B的啟動(dòng)類
@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"); // 激活開(kāi)發(fā)環(huán)境配置
application.run(args);
}
}
6.4 模塊A的自動(dòng)配置文件
# 模塊A的META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports com.example.moduleA.config.ResourcesConfig com.example.moduleA.handler.GlobalExceptionHandler
七、總結(jié)與最佳實(shí)踐(代碼視角)
7.1 核心總結(jié)
- 自動(dòng)配置類必須通過(guò)
AutoConfiguration.imports顯式聲明:- 例如:在模塊A的
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports中列出所有自動(dòng)配置類。
- 例如:在模塊A的
- Bean注冊(cè)需通過(guò)
@Bean或?qū)崿F(xiàn)WebMvcConfigurer:- 如
CorsFilter通過(guò)@Bean注冊(cè),WebMvcConfigurer方法需在@AutoConfiguration類中實(shí)現(xiàn)。
- 如
- 包掃描路徑必須覆蓋所有模塊:
- 模塊B的啟動(dòng)類需顯式掃描模塊A的包路徑。
7.2 最佳實(shí)踐代碼模板
7.2.1 模塊A的自動(dòng)配置類模板
@AutoConfiguration
@ConditionalOnClass(DispatcherServlet.class) // 依賴Servlet環(huán)境
public class ResourcesConfig implements WebMvcConfigurer {
// 跨域、攔截器等配置
@Bean
public GlobalExceptionHandler globalExceptionHandler() {
return new GlobalExceptionHandler(); // 手動(dòng)注冊(cè)異常處理器
}
}
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("系統(tǒng)內(nèi)部錯(cuò)誤");
}
}
八、附錄:工具與命令
8.1 依賴樹(shù)分析
mvn dependency:tree
8.2 日志級(jí)別調(diào)試
java -jar app.jar --logging.level.root=DEBUG
8.3 模塊間依賴驗(yàn)證
# Gradle檢查依賴沖突 ./gradlew dependencies --configuration compileClasspath
九、補(bǔ)充
1. @AutoConfiguration注解詳解
1.1 基本概念
- 定義:
@AutoConfiguration是Spring Boot 3.x引入的注解,用于標(biāo)記一個(gè)類為自動(dòng)配置類,其作用是簡(jiǎn)化自動(dòng)配置類的聲明,無(wú)需在META-INF/spring.factories中手動(dòng)注冊(cè)。 - 作用:
- 自動(dòng)注冊(cè)到Spring容器:被
@AutoConfiguration標(biāo)注的類會(huì)被Spring Boot自動(dòng)識(shí)別為自動(dòng)配置類。 - 按需加載:結(jié)合條件注解(如
@ConditionalOnClass),僅在滿足條件時(shí)生效。 - 模塊化配置:適用于多模塊項(xiàng)目,將配置邏輯封裝到獨(dú)立模塊中。
- 自動(dòng)注冊(cè)到Spring容器:被
1.2 @AutoConfiguration與@Configuration的區(qū)別
| 特性 | @AutoConfiguration | @Configuration |
|---|---|---|
| 作用 | 自動(dòng)配置類,無(wú)需手動(dòng)注冊(cè) | 普通配置類,需通過(guò)其他方式注冊(cè) |
| 自動(dòng)注冊(cè) | 自動(dòng)注冊(cè)到Spring容器(需配合AutoConfiguration.imports) | 需顯式注冊(cè)(如通過(guò)組件掃描或@Import) |
| 適用場(chǎng)景 | 自動(dòng)配置場(chǎng)景(如多模塊共享配置) | 通用配置類(如自定義Bean) |
| 是否需要額外配置 | 需在AutoConfiguration.imports文件中聲明 | 無(wú)需額外配置(但需被Spring容器掃描) |
| 依賴關(guān)系 | 通常與@Conditional注解結(jié)合 | 可獨(dú)立使用,但需手動(dòng)管理Bean依賴 |
1.3 @AutoConfiguration的使用場(chǎng)景
場(chǎng)景1:多模塊共享配置
// 模塊A的ResourcesConfig.java
@AutoConfiguration
@ConditionalOnWebApplication(type = Type.SERVLET)
public class ResourcesConfig implements WebMvcConfigurer {
// 跨域配置、攔截器等
}
- 關(guān)鍵點(diǎn):
- 通過(guò)
@AutoConfiguration標(biāo)記為自動(dòng)配置類。 - 在模塊A的
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件中聲明該類。 - 模塊B引用模塊A后,無(wú)需手動(dòng)導(dǎo)入,Spring Boot會(huì)自動(dòng)加載。
- 通過(guò)
場(chǎng)景2:替代舊版spring.factories
# Spring Boot 2.x的spring.factories(需手動(dòng)注冊(cè)) org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.example.moduleA.config.ResourcesConfig,\ com.example.moduleA.handler.GlobalExceptionHandler
- Spring Boot 3.x的改進(jìn):
使用@AutoConfiguration+AutoConfiguration.imports文件,無(wú)需維護(hù)冗長(zhǎng)的spring.factories。
2. @Bean注解詳解
2.1 基本概念
- 定義:
@Bean是Spring框架的核心注解,用于將方法返回的對(duì)象注冊(cè)為Spring容器管理的Bean。 - 作用:
- 顯式聲明Bean:開(kāi)發(fā)者通過(guò)方法定義Bean的創(chuàng)建邏輯。
- 依賴注入:方法參數(shù)支持依賴注入(如
@Autowired)。 - 靈活控制:可指定Bean作用域、初始化方法、條件等。
- 作用域控制:通過(guò)@Scope指定Bean的作用域(如singleton、prototype)。
2.2 @Bean的使用場(chǎng)景
場(chǎng)景1:定義基礎(chǔ)Bean
@Configuration
public class DataSourceConfig {
@Bean
@ConditionalOnMissingBean(DataSource.class) // 僅當(dāng)容器中沒(méi)有DataSource時(shí)生效
public DataSource dataSource() {
HikariDataSource ds = new HikariDataSource();
ds.setJdbcUrl("jdbc:mysql://localhost:3306/test");
return ds;
}
}
- 關(guān)鍵點(diǎn):
- 通過(guò)
@Bean將dataSource()方法返回的HikariDataSource注冊(cè)為Bean。 - 結(jié)合
@ConditionalOnMissingBean避免與用戶自定義Bean沖突。
- 通過(guò)
場(chǎng)景2:注冊(cè)第三方庫(kù)Bean
@Configuration
public class JsonConfig {
@Bean
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd"));
return mapper;
}
}
- 關(guān)鍵點(diǎn):
- 將第三方庫(kù)的
ObjectMapper注冊(cè)為Spring Bean,方便全局使用。
- 將第三方庫(kù)的
場(chǎng)景3:作用域控制
@Bean
@Scope("prototype") // 每次請(qǐng)求創(chuàng)建新實(shí)例
public MyPrototypeBean prototypeBean() {
return new MyPrototypeBean();
}
3. @Configuration與@Bean的協(xié)作關(guān)系
3.1 基礎(chǔ)配置類結(jié)構(gòu)
@Configuration // 標(biāo)記為配置類
public class MyAutoConfiguration {
@Bean // 定義Bean
public MyService myService() {
return new MyServiceImpl();
}
}
- 關(guān)鍵點(diǎn):
@Configuration是配置類的“身份標(biāo)識(shí)”。@Bean是配置類中定義Bean的“工具”。
4. 為什么必須使用@AutoConfiguration?能否用@Configuration替代?
4.1 必須使用@AutoConfiguration的情況
- 場(chǎng)景:在多模塊項(xiàng)目中,模塊A的配置需被模塊B自動(dòng)加載。
- 原因:
@AutoConfiguration配合AutoConfiguration.imports文件,無(wú)需手動(dòng)注冊(cè)。- 如果僅用
@Configuration,需通過(guò)以下方式顯式加載:- 在模塊B的啟動(dòng)類中指定掃描路徑。
- 通過(guò)
@Import(ResourcesConfig.class)導(dǎo)入。 - 在
spring.factories中注冊(cè)(Spring Boot 2.x方式)。
- 結(jié)論:在Spring Boot 3.x中,
@AutoConfiguration是更簡(jiǎn)潔的解決方案。
4.2 @Configuration的替代方案
// 方案1:在模塊B啟動(dòng)類中顯式掃描模塊A的包
@SpringBootApplication(scanBasePackages = {"com.example.moduleA", "com.example.moduleB"})
public class ModuleBApplication { ... }
// 方案2:使用@Import導(dǎo)入配置類
@Configuration
@Import(ResourcesConfig.class)
public class ModuleBConfig { ... }
- 缺點(diǎn):
- 需手動(dòng)維護(hù)包路徑或?qū)腙P(guān)系,耦合性更高。
- 不具備條件化加載能力(除非手動(dòng)添加
@Conditional注解)。
5. 示例代碼中的關(guān)鍵注解解析
5.1 ResourcesConfig示例
@AutoConfiguration
@ConditionalOnWebApplication(type = Type.SERVLET)
public class ResourcesConfig implements WebMvcConfigurer {
@Bean
public CorsFilter corsFilter() { ... }
@Override
public void addInterceptors(InterceptorRegistry registry) { ... }
}
- 關(guān)鍵點(diǎn):
- @AutoConfiguration:聲明為自動(dòng)配置類。
- @ConditionalOnWebApplication:僅在Servlet環(huán)境生效。
- @Bean:將
CorsFilter注冊(cè)為Bean。 - 實(shí)現(xiàn)WebMvcConfigurer:通過(guò)繼承接口直接擴(kuò)展Spring MVC配置。
5.2 全局異常處理器示例
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<String> handleGlobalException(Exception e) { ... }
}
- 關(guān)鍵點(diǎn):
@RestControllerAdvice:標(biāo)記為全局異常處理類。- 無(wú)需
@Bean,因?yàn)镾pring通過(guò)組件掃描自動(dòng)識(shí)別。
6. 常見(jiàn)問(wèn)題與解答
Q1:為什么我的自動(dòng)配置類未被加載?
- 可能原因:
- 未在
AutoConfiguration.imports文件中聲明類。 - 依賴未正確引入(如模塊B未依賴模塊A)。
- 條件注解未滿足(如
@ConditionalOnClass的類不存在)。
- 未在
- 解決方案:
- 檢查
AutoConfiguration.imports文件路徑是否正確。 - 確保模塊B的POM中包含模塊A的依賴。
- 在啟動(dòng)日志中搜索
Positive matches,確認(rèn)條件是否滿足。
- 檢查
Q2:@Bean和@Component的區(qū)別?
| 注解 | 作用范圍 | 使用場(chǎng)景 |
|---|---|---|
@Bean | 方法級(jí) | 在配置類中定義Bean的創(chuàng)建邏輯 |
@Component | 類級(jí) | 通過(guò)組件掃描自動(dòng)注冊(cè)Bean |
Q3:為什么自動(dòng)配置類需要實(shí)現(xiàn)WebMvcConfigurer?
- 原因:
Spring MVC的擴(kuò)展機(jī)制允許通過(guò)實(shí)現(xiàn)WebMvcConfigurer接口或使用@Bean注冊(cè)WebMvcConfigurer來(lái)添加攔截器、跨域配置等。 - 示例:
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new MyInterceptor());
}
7. 完整自動(dòng)配置類代碼示例
// 模塊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. 關(guān)鍵配置文件說(shuō)明
8.1 AutoConfiguration.imports文件
# 模塊A的META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports com.example.moduleA.config.ResourcesConfig
- 作用:
告知Spring Boot哪些類是自動(dòng)配置類,無(wú)需手動(dòng)注冊(cè)到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
- 兼容性說(shuō)明:
Spring Boot 3.x支持同時(shí)使用兩種方式,但推薦使用@AutoConfiguration。
以上就是SpringBoot多模塊自動(dòng)配置失效問(wèn)題的解決方案的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot多模塊自動(dòng)配置失效的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
基于Java SSM框架實(shí)現(xiàn)簡(jiǎn)易的評(píng)教系統(tǒng)
這篇文章主要介紹了通過(guò)Java SSM框架實(shí)現(xiàn)一個(gè)簡(jiǎn)易的評(píng)教系統(tǒng)的示例代碼,文中的代碼講解詳細(xì),感興趣的小伙伴可以了解一下2022-02-02
springBoot之如何獲取接口請(qǐng)求數(shù)據(jù)和返回?cái)?shù)據(jù)實(shí)現(xiàn)日志
這篇文章主要介紹了springBoot之如何獲取接口請(qǐng)求數(shù)據(jù)和返回?cái)?shù)據(jù)實(shí)現(xiàn)日志問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04
Spring @ExceptionHandler注解統(tǒng)一異常處理和獲取方法名
這篇文章主要介紹了Spring注解之@ExceptionHandler 統(tǒng)一異常處理和獲取方法名,在實(shí)際項(xiàng)目中,合理使用@ExceptionHandler能夠提高代碼的可維護(hù)性和用戶體驗(yàn),通過(guò)本文的解析和實(shí)踐,讀者可以更好地理解和掌握@ExceptionHandler的用法和原理2023-09-09
SpringBoot接口數(shù)據(jù)加解密實(shí)戰(zhàn)記錄
現(xiàn)今對(duì)于大多數(shù)公司來(lái)說(shuō),信息安全工作尤為重要,下面這篇文章主要給大家介紹了關(guān)于SpringBoot接口數(shù)據(jù)加解密的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-07-07
解決mybatisplus MetaObjectHandler 失效的問(wèn)題
本文主要介紹了解決mybatisplus MetaObjectHandler 失效的問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-02-02
java后端把數(shù)據(jù)轉(zhuǎn)換為樹(shù),map遞歸生成json樹(shù),返回給前端(后臺(tái)轉(zhuǎn)換)
這篇文章主要介紹了java后端把數(shù)據(jù)轉(zhuǎn)換為樹(shù),map遞歸生成json樹(shù),返回給前端實(shí)例(后臺(tái)轉(zhuǎn)換),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2017-01-01
使用Spring的攔截器監(jiān)測(cè)每個(gè)Controller或方法的執(zhí)行時(shí)長(zhǎng)
這篇文章主要介紹了使用Spring的攔截器監(jiān)測(cè)每個(gè)Controller或方法的執(zhí)行時(shí)長(zhǎng),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-10-10

