SpringBoot启动类默认自动扫描包范围 + spring.factories理解

本文介绍了SpringBoot中组件扫描的三种方式,包括启动类的@ComponentScan注解、使用@Import注解以及创建spring.factories文件。详细讲解了spring.factories的配置和作用,以及如何解决SpringBoot拦截器中Bean注入失败的问题。通过修改配置,确保拦截器中的Bean能够正确注入。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

下面的几种方法:

注解@ComponentScan、注解@import、创建spring.factories文件、 都可以注入其他模块的bean到spring容器中。

一:SpringBoot启动类配置默认自动扫描包范围

(其他公共模块引入,使用这种方式报错bean没有注入)不知道原因

SpringBoot应用启动时,默认会自动扫描与启动类在同个包以及子包下的Bean。

所以当启动类所在的包名与项目子模块等的包名不一致时,可以在启动类上添加包扫描注解:该注解会扫描配置的包的和其子包下的bean

package com.xxx.app.bff.service;
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.ComponentScan;
 
@EnableDiscoveryClient
@SpringBootApplication
@ComponentScan(value = {"com.xxx.app.bff.service.*", "com.xxx.app.bff.sdk.*"})
public class AppApplication {
    public static void main(String[] args) {
        SpringApplication.run(AppApplication.class, args);
    }
}

需要注意的是,一旦指定了@ComponentScan,则将不会在默认的启动类的包名下扫描注入容器,因此在扫描列表中还需要单独添加启动类所在的包

SpringBoot启动类自动包扫描 三种方式_风.foxwho的博客-CSDN博客_springboot指定扫描包的方式

----------------------------------------------------------------------------------------------------------------------------

二:SpringBoot 之 spring.factories理解和import理解

为什么 Spring Boot 宁可挨骂也要干掉 spring.factories ?-CSDN博客(重要)

在springboot项目中,我们常常会在子模块中创建公共类库,那么在另一个模块中,需要加载配置文件时,往往springboot自动扫描包只能默认扫描到自己模块下的类,那我们如何解决?

springboot核心基础之spring.factories机制 - 知乎

方法一:在Spring Boot Application 主类上使用@Import注解。

关于@Import 注解有不懂的同学,建议自行学习。

方法二:创建spring.factories文件(有用)

现在我们将其改造一下,采用spring.factories 的方式去加载SwaggerConfig类,在resources目录下新建一个META-INF 的目录,然后在

新建一个spring.factories 的文件,里面的内容为:

然后在把Spring Boot 启动类上的@Import注释掉,启动发现也可以把SwaggerConfig加载到Spring 容器中:

注意:spring.factories中不能配置接口,必须是实现类

到这就完成了加载一个Spring 不能扫描到的一个类,他可以是第三方的,也可以是自己写的,只要是Spring Boot 默认扫描路径不能够扫描到,都可以使用这种方式去加载。

spring-boot包中的spring.factories文件

在Spring Boot 的很多包中都能够找到spring.factories,下面就是spring-boot 包中的spring.factories文件。

# PropertySource Loaders
org.springframework.boot.env.PropertySourceLoader=\
org.springframework.boot.env.PropertiesPropertySourceLoader,\
org.springframework.boot.env.YamlPropertySourceLoader


# Run Listeners
org.springframework.boot.SpringApplicationRunListener=\
org.springframework.boot.context.event.EventPublishingRunListener


# Error Reporters
org.springframework.boot.SpringBootExceptionReporter=\
org.springframework.boot.diagnostics.FailureAnalyzers


# Application Context Initializers
org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
org.springframework.boot.context.ContextIdApplicationContextInitializer,\
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\
org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer


# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.ClearCachesApplicationListener,\
org.springframework.boot.builder.ParentContextCloserApplicationListener,\
org.springframework.boot.context.FileEncodingApplicationListener,\
org.springframework.boot.context.config.AnsiOutputApplicationListener,\
org.springframework.boot.context.config.ConfigFileApplicationListener,\
org.springframework.boot.context.config.DelegatingApplicationListener,\
org.springframework.boot.context.logging.ClasspathLoggingApplicationListener,\
org.springframework.boot.context.logging.LoggingApplicationListener,\
org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener


# Environment Post Processors
org.springframework.boot.env.EnvironmentPostProcessor=\
org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,\
org.springframework.boot.env.SpringApplicationJsonEnvironmentPostProcessor,\
org.springframework.boot.env.SystemEnvironmentPropertySourceEnvironmentPostProcessor


# Failure Analyzers
org.springframework.boot.diagnostics.FailureAnalyzer=\
org.springframework.boot.diagnostics.analyzer.BeanCurrentlyInCreationFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BeanNotOfRequiredTypeFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BindFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.BindValidationFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.UnboundConfigurationPropertyFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.ConnectorStartFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.NoUniqueBeanDefinitionFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.PortInUseFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.ValidationExceptionFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyNameFailureAnalyzer,\
org.springframework.boot.diagnostics.analyzer.InvalidConfigurationPropertyValueFailureAnalyzer


# FailureAnalysisReporters
org.springframework.boot.diagnostics.FailureAnalysisReporter=\
org.springframework.boot.diagnostics.LoggingFailureAnalysisReporter

在日常工作中,我们可能需要实现一些SDK 或者Sring boot starter 给别人用的时候,我们就可以使用Factories机制,Factories机制可以让SDK或者Stater的使用只需要很少或者不需要进行配置,只需要在服务中引入我们的Jar包就即可。

例如:mybatis-plus能被spring管理起来主要是项目启动类的联合注解@SpringBootApplication有一个自动装配的注解@EnableAutoConfiguration,只要有这个注解项目在启动的时候就会在引入的jar中找是否存在spring.factories的配置文件,如果找到此配置文件,将会根据此配置文件找到对应的配置类,处理jar内部需要提取的配置信息以及将需要加载到的component交给spring管理。

三、spring的拦截器中,bean注入失败问题

Bean 注入失败问题汇总-CSDN博客 --优质博客

拦截器的配置类是以new JwtInterceptor的方式使用的,那么这个JwtInterceptor不受Spring管理。因此,JwtInterceptor里边@Autowired注入JavaJwtUtil是不会注入进去的。

有问题的:

@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new JwtInterceptor());
    }
}

修改为:配置类中将new JwtInterceptor()改为Bean的方式


@Configuration
public class InterceptorConfig implements WebMvcConfigurer {
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(getJwtInterceptor());
    }
    @Bean
    JwtInterceptor getJwtInterceptor() {
        return new JwtInterceptor();
    }
}

Spring拦截器中注入Bean失败解放方案详解_java_脚本之家

@Slf4j
public class JwtInterceptor implements HandlerInterceptor {
    @Autowired
    JavaJwtUtil javaJwtUtil;
    List<String> whiteList = Arrays.asList(
            "/auth/login",
            "/error"
    );
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response,
                             Object handler) throws Exception {
        // 如果不是映射到方法直接通过
        if (!(handler instanceof Handl。。。。。。。。。。。。。。。。。。

<think>好的,我现在需要回答用户关于Spring Boot自动装配原理的问题。用户提到在面试中被问到,他回答说基于启动类的@SpringBootApplication注解,其中含@EnableAutoConfiguration,该注解会扫描spring.factories文件中的配置,将依赖中的注解转为Bean对象,实现开箱即用。用户想知道这样的回答是否正确,并希望得到改进建议。 首先,我需要确认用户回答的正确性。@SpringBootApplication确实是一个组合注解,含@EnableAutoConfiguration,而@EnableAutoConfiguration的作用是启用自动配置。Spring Boot通过spring.factories文件来加载自动配置类,这些配置类通常位于各个starter依赖中,根据条件注解(如@ConditionalOnClass)来决定是否加载对应的Bean。因此,用户回答的大方向是对的,但可能存在一些细节上的不准确或遗漏。 接下来,我需要分析用户回答中的亮点和不足。亮点可能括正确指出了核心注解和spring.factories的作用。不足之处可能涉及对@SpringBootApplication其他组成部分的忽略(如@ComponentScan),自动配置的具体机制(条件注解的作用),以及spring.factories的路径和加载过程的详细说明。 然后,我需要考虑必须纠正的关键错误。例如,用户可能误以为所有依赖的注解都会被自动转换为Bean,但实际上自动配置是基于条件注解有选择性地进行的。此外,用户可能没有提到@Import(AutoConfigurationImportSelector.class)的作用,这是@EnableAutoConfiguration的关键部分,负责加载自动配置类。 接下来,补充核心机制。需要详细说明自动配置的工作流程,括如何通过spring.factories发现配置类,条件注解如何判断是否加载Bean,以及@SpringBootApplication中的@ComponentScan如何扫描用户自定义的Bean。此外,可以引入自动配置类的结构示例,帮助理解其内部实现。 建议的回答框架应该结构清晰,分点阐述基本定义、核心注解、工作流程、条件装配机制以及可能的高频追问点。使用Mermaid图表可以更直观地展示自动配置的流程,增强理解。 最后,优化回答示例需要整合上述要点,确保准确、全面,同时避免技术术语的误用。例如,明确spring.factories的位置(META-INF目录下),自动配置类的筛选过程,以及条件注解的具体应用场景。 在思考过程中,还需考虑用户可能的疑惑点,比如自动配置与组件扫描的区别,starter的工作原理,以及如何自定义自动配置。这些都可能成为面试中的追问问题,提前准备答案有助于用户更好地应对。 总结来说,用户回答基本正确,但需要补充细节,纠正术语,明确机制,并结构化为更专业的表达方式。</think>--- ### 一、回答的亮点与不足 #### **优点**: 1. 正确指出`@SpringBootApplication`是核心入口注解 2. 明确`@EnableAutoConfiguration`触发自动装配 3. 提到`spring.factories`配置文件的扫描机制 #### **不足**: 1. **关键组件缺失**:未说明`AutoConfigurationImportSelector`的核心作用 2. **路径描述错误**:实际扫描的是`META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports`(Spring Boot 2.7+)或`spring.factories`(旧版本) 3. **条件装配机制缺失**:未提及`@Conditional`系列注解的筛选逻辑 4. **注解层级混淆**:将"注解转Bean"简化为自动装配过程,易产生误解 --- ### 二、必须纠正的关键错误 #### **错误1**:依赖的注解自动转Bean ✅ **修正表述**: 自动装配通过**条件化配置类**注册Bean,而非简单扫描所有注解。例如: ```java @Configuration @ConditionalOnClass(DataSource.class) // 仅当类路径存在DataSource时生效 public class DataSourceAutoConfiguration { @Bean @ConditionalOnMissingBean // 仅当容器中没有该Bean时创建 public DataSource dataSource() { return new HikariDataSource(); } } ``` #### **错误2**:spring.factories直接定义Bean ✅ **精确说明**: `spring.factories`中定义的是**自动配置类**(含条件判断逻辑的配置类),这些类根据当前环境决定是否注册具体Bean --- ### 三、应补充的核心机制 #### 1. 自动装配流程 ```mermaid graph TD A[启动类@SpringBootApplication] --> B[加载@EnableAutoConfiguration] B --> C[AutoConfigurationImportSelector] C --> D{读取META-INF/spring/*.imports} D --> E[加载所有自动配置类] E --> F{执行@Conditional条件检查} F -->|条件满足| G[注册对应Bean] F -->|条件不满足| H[跳过配置类] ``` #### 2. 核心组件作用 | 组件 | 作用 | |------|------| | `@SpringBootApplication` | 复合注解:含`@SpringBootConfiguration`+`@EnableAutoConfiguration`+`@ComponentScan` | | `AutoConfigurationImportSelector` | 实现`ImportSelector`接口,负责加载自动配置类 | | `spring-autoconfigure-metadata.properties` | 预过滤条件元数据,加速启动过程 | #### 3. 条件注解类型 | 注解 | 作用场景 | |------|----------| | `@ConditionalOnClass` | 类路径存在指定类时生效 | | `@ConditionalOnMissingBean` | 容器中无指定Bean时生效 | | `@ConditionalOnProperty` | 配置参数符合条件时生效 | | `@ConditionalOnWebApplication` | Web环境生效 | --- ### 四、建议回答框架 #### **分层表述法**: ```markdown 1. **启动入口** `@SpringBootApplication`是组合注解,含: - `@SpringBootConfiguration`:标记主配置类 - `@ComponentScan`:扫描路径(默认当前) - `@EnableAutoConfiguration`:激活自动装配 2. **自动装配触发** `@EnableAutoConfiguration`通过`AutoConfigurationImportSelector`: - 从`META-INF/spring/*.imports`加载候选配置类(Spring Boot 2.7+) - 旧版本使用`spring.factories`中的`EnableAutoConfiguration`键值列表 3. **条件过滤阶段** 对候选配置类进行筛选: ```java // 示例:DataSource自动配置 @Configuration @ConditionalOnClass({DataSource.class, EmbeddedDatabaseType.class}) @ConditionalOnMissingBean(type = "io.r2dbc.spi.ConnectionFactory") public class DataSourceAutoConfiguration { // 具体Bean定义 } ``` 4. **配置类执行** 通过`@Import`将筛选后的配置类加入容器,最终注册符合条件的Bean ``` --- ### 五、高频追问应对 #### **问题1**:如何自定义自动配置? **回答要点**: 1. 创建`META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports`文件 2. 编写配置类并添加`@Configuration`和`@Conditional`条件 3. 使用`@AutoConfigureOrder`控制加载顺序 4. 通过`spring-autoconfigure-metadata.properties`优化加载性能 #### **问题2**:自动配置与组件扫描的区别? **回答模板**: "自动配置通过条件判断注册第三方依赖的Bean,而`@ComponentScan`主要用于扫描用户自定义的`@Component`类。自动配置类的加载优先级高于组件扫描,但用户可通过定义同名Bean覆盖自动配置。" --- ### 六、优化回答示例 "Spring Boot的自动装配原理基于`@SpringBootApplication`中的`@EnableAutoConfiguration`。该注解通过`AutoConfigurationImportSelector`加载`META-INF/spring/*.imports`(或旧版`spring.factories`)中声明的配置类。这些配置类使用`@Conditional`系列注解进行条件判断,仅当类路径存在特定依赖、配置参数符合要求等条件满足时,才会注册对应的Bean到容器。整个过程通过条件化装配实现开箱即用,同时允许开发者自定义覆盖默认配置。" 该回答明确了配置加载路径、条件判断机制和覆盖能力,建议补充以下内容: 1. Spring Boot 2.7+的配置路径变更 2. `@Configuration`与`@AutoConfiguration`的区别 3. 自动配置与Starter的关系
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值