一、Bean 扫描机制
SpringBoot 简化了传统 Spring 的组件扫描配置,核心规则如下:
1. 传统配置方式
- XML 配置:
<context:component-scan base-package="com.itheima"/> - 注解配置:
@ComponentScan(basePackages = "com.itheima")
2. SpringBoot 自动扫描规则
@SpringBootApplication注解默认包含@ComponentScan,默认扫描启动类所在包及其所有子包。- 项目结构示例:启动类
SpringbootQuickstartApplication位于com.itheima.springbootquickstart包下,会自动扫描该包及controller、service等子包下的所有组件。
二、Bean 注册的四种方式
1. 自定义 Bean:@Component 及其衍生注解
适用于自己编写的类,通过注解标记后被自动扫描注册。
表格
| 注解 | 说明 | 适用场景 |
|---|---|---|
@Component |
基础注解,标记为 Spring 组件 | 不属于以下三类的通用类 |
@Controller |
@Component 衍生注解 |
标注在控制器类上 |
@Service |
@Component 衍生注解 |
标注在业务逻辑类上 |
@Repository |
@Component 衍生注解 |
标注在数据访问类上(MyBatis 场景下使用较少) |
2. 第三方 Bean:@Bean 注解
适用于无法直接修改源码的第三方类(如工具类、框架类),通过配置类注册。
基础用法
java
运行
// 推荐:单独配置类,集中管理第三方 Bean
@Configuration
public class CommonConfig {
@Bean
public Resolver resolver() {
return new Resolver(); // Resolver 为第三方类
}
}
⚠️ 不建议直接在启动类中使用 @Bean,会导致代码混乱,不利于维护。
3. 第三方 Bean:@Import 注解
适用于批量导入配置类或实现 ImportSelector 接口动态导入类。
方式 1:直接导入配置类
java
运行
@SpringBootApplication
@Import(CommonConfig.class) // 导入配置类,其中的 @Bean 会被注册
public class SpringbootRegistApplication {
}
方式 2:实现 ImportSelector 接口
通过接口实现类动态返回需要导入的类全限定名,可从配置文件读取导入类。
java
运行
public class CommonImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
// 从配置文件读取要导入的类
List<String> imports = new ArrayList<>();
try (BufferedReader br = new BufferedReader(
new InputStreamReader(CommonImportSelector.class.getClassLoader()
.getResourceAsStream("common.imports")))) {
String line;
while ((line = br.readLine()) != null) {
imports.add(line);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
return imports.toArray(new String[0]);
}
}
在启动类中导入:
java
运行
@SpringBootApplication
@Import(CommonImportSelector.class)
public class SpringbootRegistApplication {
}
方式 3:@EnableXxxx 注解
封装 @Import 注解,例如 @EnableWebMvc、@EnableTransactionManagement,本质是通过注解触发 @Import 导入相关配置类。
三、Bean 注册条件控制:@Conditional 系列注解
SpringBoot 提供了条件注解,只有满足条件时,Bean 才会被注册到 IOC 容器中。
表格
| 注解 | 生效条件 |
|---|---|
@ConditionalOnProperty |
配置文件中存在指定属性时,才注册该 Bean |
@ConditionalOnMissingBean |
容器中不存在当前类型的 Bean 时,才注册该 Bean |
@ConditionalOnClass |
当前环境中存在指定类时,才注册该 Bean |
示例:
java
运行
@Bean
@ConditionalOnProperty(prefix = "oss", name = "enabled", havingValue = "true")
public OssClient ossClient() {
// 只有配置文件中 oss.enabled=true 时,才注册 OssClient
return new OssClient();
}
四、核心总结
表格
| 注册方式 | 适用场景 | 优点 |
|---|---|---|
@Component 及其衍生注解 |
自定义类 | 简单直接,自动扫描 |
@Bean |
第三方类、需自定义创建逻辑的类 | 灵活控制 Bean 创建过程 |
@Import |
批量导入配置、动态导入类 | 支持配置文件驱动的动态导入 |
@Conditional 系列 |
按条件注册 Bean | 实现环境感知的自动配置 |