Spring中几个自动注入的注解的优先级

本文详细阐述了在Spring框架中,@Resource、@Autowired、@Qualifier和@Primary四个注解的注入优先级。当接口只有一个实现类时,@Resource和@Autowired效果相同,@Primary的使用影响不大。而在存在多个实现类的情况下,@Qualifier优先级高于@Primary,而@Resource的优先级最高。总结了在不同场景下如何选择和组合这些注解以实现准确的依赖注入。

本文讨论以下几个注解的优先级:

@Resource    javax.annotation.Resource;
@Autowired   org.springframework.beans.factory.annotation.Autowired;
@Qualifier   org.springframework.beans.factory.annotation.Qualifier
@Primary     org.springframework.context.annotation.Primary

说明:

@Resource通过byName注入

@Autowired通过byType注入

@Qualifier用于指定bean的名称

@Primary用来指定某个接口的优先实现(默认使用被该注解所注解的类的对象)

优先级关系

接口只有一个实现类

@Resource @Autowired 效果一样

@Primary 加不加无所谓;@Qualifier 不要加,除非你能保证@Qualifier 的value指定了正确的bean名称,或者不指定value,但变量名为正确的bean名称

接口有多个实现类

@Autowired @Qualifier @Primary 一起用,@Qualifier > @Primary

@Resource @Qualifier @Primary 一起用,@Resource > @Qualifier > @Primary

简言之:

@Autowired 在这种情况下只能作为自动注入的标识,无法用于寻找bean;

如果有@Resource,那么先用变量名作为bean的名字去查找bean,如果找到了,那就将该bean赋值给变量;

如果没有找到,那么再根据@Qualifier的value作为bean的名字去查找bean,找到则将该bean赋值给变量,没找到则报错;

如果@Resource、@Qualifier都没有,只有@Autowired, 但有且仅有一个子类被@Primary注解,那么将使用被@Primary注解的子类的bean进行注入

<think> 我们正在讨论Spring Boot的三个核心问题:自动配置原理、自定义Starter方法、以及@SpringBootApplication注解的组成。下面我将逐一详细解释。 ### 1. Spring Boot自动配置原理 Spring Boot的自动配置(Auto-configuration)是其核心特性之一,它基于条件化配置(Conditional Configuration)实现,主要依赖`spring-boot-autoconfigure`模块。其工作原理可分为以下几个步骤: #### (1) 条件注解驱动 Spring Boot定义了一系列`@Conditional`派生注解(如`@ConditionalOnClass`, `@ConditionalOnBean`, `@ConditionalOnProperty`等),用于判断是否满足特定条件。例如: ```java @Configuration @ConditionalOnClass(DataSource.class) // 当类路径存在DataSource类时生效 public class DataSourceAutoConfiguration { // 自动配置逻辑 } ``` #### (2) 配置加载机制 - **自动配置声明文件**:在`META-INF/spring.factories`中通过`org.springframework.boot.autoconfigure.EnableAutoConfiguration`键列出所有自动配置类: ```properties org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\ org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration ``` #### (3) 配置优先级 自动配置的优先级低于用户显式配置(如`@Bean`方法),遵循**覆盖原则**。 #### (4) 执行流程 1. Spring Boot启动时加载`spring.factories`中的自动配置类 2. 根据条件注解筛选有效的配置类 3. 按顺序加载符合条件的配置类(使用`@AutoConfigureOrder`控制顺序) > **关键点**:自动配置的本质是**标准Spring配置类的条件化加载**[^1]。 ### 2. 自定义Spring Boot Starter方法 创建自定义Starter包含以下步骤: #### (1) 命名规范 - 官方Starter命名:`spring-boot-starter-{name}` - 自定义Starter命名:`{name}-spring-boot-starter` #### (2) 项目结构 ``` my-starter ├── src/main/java │ ├── com/example/autoconfigure │ │ ├── MyServiceAutoConfiguration.java // 自动配置类 │ │ └── MyServiceProperties.java // 配置属性类 ├── src/main/resources │ ├── META-INF │ │ └── spring.factories // 自动配置注册文件 ``` #### (3) 核心代码实现 - **定义配置属性类**(绑定application.properties中的参数): ```java @ConfigurationProperties(prefix = "my.service") public class MyServiceProperties { private String apiKey; private int timeout = 5000; // getters & setters } ``` - **自动配置类**: ```java @Configuration @EnableConfigurationProperties(MyServiceProperties.class) @ConditionalOnClass(MyService.class) public class MyServiceAutoConfiguration { @Bean @ConditionalOnMissingBean public MyService myService(MyServiceProperties properties) { return new MyService(properties.getApiKey(), properties.getTimeout()); } } ``` - **注册自动配置**(`src/main/resources/META-INF/spring.factories`): ```properties org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.example.autoconfigure.MyServiceAutoConfiguration ``` #### (4) 使用Starter 用户引入依赖后,可直接注入`MyService`: ```java @Service public class UserService { private final MyService myService; public UserService(MyService myService) { this.myService = myService; } } ``` 并在`application.properties`中配置参数: ```properties my.service.api-key=123abc my.service.timeout=3000 ``` ### 3. `@SpringBootApplication`注解解析 `@SpringBootApplication`是一个组合注解,包含三个核心注解: ```java @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @SpringBootConfiguration // 继承自@Configuration,标识该类为配置类 @EnableAutoConfiguration // 启用自动配置功能 @ComponentScan( // 包扫描路径(默认当前类所在包及其子包) excludeFilters = @Filter( type = FilterType.CUSTOM, classes = TypeExcludeFilter.class ) ) public @interface SpringBootApplication { // 属性可覆盖@ComponentScan的basePackages等参数 } ``` #### 注解层级关系: $$ \begin{array}{c} \text{@SpringBootApplication} \\ \downarrow \\ \begin{array}{c} \text{@SpringBootConfiguration} \\ \downarrow \\ \text{@Configuration} \\ \end{array} \\ + \\ \begin{array}{c} \text{@EnableAutoConfiguration} \\ \end{array} \\ + \\ \begin{array}{c} \text{@ComponentScan} \\ \end{array} \end{array} $$ #### 功能详解: 1. **@SpringBootConfiguration** 表明该类是Spring Boot的配置类,允许注册额外的Bean或导入其他配置类。 2. **@EnableAutoConfiguration** 激活Spring Boot的自动配置机制,根据依赖自动配置Spring应用。 3. **@ComponentScan** 自动扫描当前包及其子包下的组件(`@Component`, `@Service`, `@Repository`, `@Controller`等)。 > **最佳实践**:主配置类应放在项目的根包(root package)下,确保扫描范围覆盖所有组件[^1]。 --- ### 总结 - **自动配置**:基于条件注解和`spring.factories`的自动Spring配置加载 - **自定义Starter**:通过自动配置类+属性绑定+`spring.factories`注册实现即插即用 - **`@SpringBootApplication`**:三大核心注解的合成体,简化启动类配置 §§相关问题§§ 1. 如果想自定义Spring Boot自动配置的条件判断规则,应该如何扩展? 2. 如何在自定义Starter中实现健康检查(HealthIndicator)? 3. `@SpringBootApplication`中的`exclude`属性有什么具体用途? 4. 如何解决多个Starter间的自动配置冲突问题? </think> ### Spring Boot 自动配置原理、自定义 Starter 方法及 `@SpringBootApplication` 注解详解 --- #### **一、Spring Boot 自动配置原理** Spring Boot 自动配置基于 **条件化装配(Conditional Beans)** 和 **约定优于配置(Convention over Configuration)** 实现,核心流程如下: 1. **扫描自动配置类** 启动时通过 `spring-boot-autoconfigure` 模块的 `META-INF/spring.factories` 文件加载所有预定义的自动配置类: ```properties # spring.factories 示例 org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration,\ org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration ``` 2. **条件注解驱动装配** 自动配置类使用 **条件注解** 判断是否生效: ```java @Configuration @ConditionalOnClass(DataSource.class) // 类路径存在DataSource时生效 @ConditionalOnProperty(prefix="spring.datasource") // 配置属性存在时生效 public class DataSourceAutoConfiguration { @Bean @ConditionalOnMissingBean // 当容器无DataSource时创建 public DataSource dataSource() { return new HikariDataSource(); } } ``` - `@ConditionalOnClass`:依赖类存在时触发配置 - `@ConditionalOnProperty`:配置参数匹配时触发 - `@ConditionalOnMissingBean`:容器无此Bean时创建[^1] 3. **优先级控制** 用户自定义配置(如 `@Bean`)优先级 **高于** 自动配置(通过 `@ConditionalOnMissingBean` 实现覆盖)。 --- #### **二、自定义 Spring Boot Starter 方法** 创建 Starter 需实现 **自动配置模块** + **依赖管理**: ##### **步骤 1:项目结构** ``` my-starter ├── src/main/java │ ├── com/example/mystarter │ │ ├── MyService.java // 核心服务类 │ │ ├── MyAutoConfiguration.java // 自动配置类 │ │ └── MyProperties.java // 配置属性类 ├── src/main/resources │ ├── META-INF │ │ └── spring.factories // 注册自动配置类 ``` ##### **步骤 2:关键代码实现** 1. **定义配置属性类**(绑定 `application.yml`): ```java @ConfigurationProperties(prefix = "my.service") public class MyProperties { private String apiKey; private int timeout = 3000; // getters & setters } ``` 2. **自动配置类**: ```java @Configuration @EnableConfigurationProperties(MyProperties.class) // 启用属性绑定 @ConditionalOnClass(MyService.class) public class MyAutoConfiguration { @Bean @ConditionalOnMissingBean public MyService myService(MyProperties properties) { return new MyService(properties.getApiKey(), properties.getTimeout()); } } ``` 3. **注册配置类**(`resources/META-INF/spring.factories`): ```properties org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.example.mystarter.MyAutoConfiguration ``` ##### **步骤 3:使用自定义 Starter** 1. 其他项目引入依赖: ```xml <dependency> <groupId>com.example</groupId> <artifactId>my-starter</artifactId> <version>1.0.0</version> </dependency> ``` 2. 在 `application.yml` 中配置参数: ```yaml my.service: api-key: "123456" timeout: 5000 ``` --- #### **三、`@SpringBootApplication` 注解解析** 该注解是合成注解(Composed Annotation),包含三个核心注解: ```java @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) @SpringBootConfiguration // ← 继承自 @Configuration @EnableAutoConfiguration // ← 启用自动配置 @ComponentScan( // ← 包扫描 excludeFilters = @Filter( type = FilterType.CUSTOM, classes = TypeExcludeFilter.class ) ) public @interface SpringBootApplication {} ``` 1. **`@SpringBootConfiguration`** - 继承自 `@Configuration`,标识该类为 **配置类**(可定义 `@Bean` 方法)。 2. **`@EnableAutoConfiguration`** - 激活 Spring Boot 的自动配置机制,根据依赖自动装配 Bean。 - 内部通过 `@Import(AutoConfigurationImportSelector.class)` 加载 `spring.factories` 中的配置类。 3. **`@ComponentScan`** - 默认扫描**当前包及其子包**下的组件(`@Component`, `@Service`, `@Controller` 等)。 - 可通过 `scanBasePackages` 属性自定义扫描路径: ```java @SpringBootApplication(scanBasePackages = "com.example.app") ``` --- ### **总结** | 机制 | 实现要点 | |---------------------|--------------------------------------------------------------------------| | **自动配置** | 基于 `spring.factories` + 条件注解(`@ConditionalOnClass` 等) | | **自定义 Starter** | 自动配置类 + `@ConfigurationProperties` + `META-INF/spring.factories` 注册 | | **`@SpringBootApplication`** | 三大核心注解:配置声明 + 自动装配 + 组件扫描 | > **最佳实践**:主启动类应放在项目**根包**(Root Package)下,确保 `@ComponentScan` 能覆盖所有组件[^1]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值