@Primary 使用

造轮子的一个小小的发现

当一个接口被两个service实现时,controller调用接口实现功能,会报错,提示开发者指定service,官方是建议你使用@Qualifier来区分的,但是,总有另一种方法实现的。

 

场景

public interface Hi{ String hi(); } 

@Service
public class Hi1 implements Hi{
    @Override
    public String hi() {
        return "hi1";
    }
}

@Service
public class Hi2 implements Hi{
    @Override
    public String hi() {
        return "hi2";
    }
}
@Controller
public class SingerService {
    @Autowired
    private Hi hi;

    public String sing(){
        return hi.hi();
    }
}
 

此时没指定具体的接口实现类,spring会报错,但是只要将Hi2改成

@Service
@Primary
public class Hi2 implements Hi{
    @Override
    public String hi() {
        return "hi2";
    }
}

 命令行就会输出

hi2

@Primary就是默认的意思,而他的使用情况当然不是用于service层了,而是在造轮子的时候,往往一个基本接口类有多次实现,我们只要给其中一个实现加上@Primary,那么在使用这个接口类的时候就不用每次都@Qualifier了,而且对于大多数开发者而言,只要理解使用默认的功能就足够了。

转载于:https://www.cnblogs.com/ydymz/p/9014571.html

<think>好的,用户想了解Spring框架中@Primary注解的用法和常见问题。首先,我需要回忆一下@Primary的作用。根据提供的引用,@Primary用于解决多个同类型Bean的依赖注入冲突。当有多个实现同一接口Bean时,Spring默认会抛出NoUniqueBeanDefinitionException,而@Primary可以指定优先注入的Bean。 接下来,我需要整理用法。根据引用[2]和[3],@Primary可以用在类上或@Bean方法上,标记为首选Bean。用户可能在配置类中使用@Bean配合@Primary,或者在组件扫描的类上直接使用。 然后,常见问题部分。用户可能会遇到多个@Primary注解的情况,这时候Spring还是会报错,需要结合@Qualifier解决。另外,@Primary的优先级低于@Qualifier,所以需要注意使用顺序。还有作用域的问题,比如原型作用域下每次注入都会创建新实例,但@Primary仍然有效。 应用场景方面,引用[3]提到多实现类、不同环境配置和避免显式指定。比如测试环境用Mock实现,生产环境用真实实现,通过@Primary切换。 示例代码部分,引用[4]展示了在类上使用@Primary,导致自动注入AudiCarService的例子。可能需要补充配置类中使用@Bean的例子。 还需要注意,@Primary和@Qualifier的区别,前者是默认首选,后者是显式指定。用户可能混淆两者的使用场景,需要解释清楚。 最后,生成相关问题,确保覆盖用法、场景、问题及与其他注解的对比。这样用户能全面了解@Primary使用和注意事项。</think>### @Primary 注解用法及常见问题 #### 一、@Primary 注解的作用 在 Spring 框架中,当存在多个相同类型的 Bean 时,依赖注入可能会引发 `NoUniqueBeanDefinitionException`。`@Primary` 注解的作用是标记某个 Bean 为“首选”,在自动装配时优先选择该 Bean,从而避免冲突[^1][^3][^4]。 #### 二、基本用法 1. **在类上直接标记** 适用于通过组件扫描(`@ComponentScan`)注册的 Bean: ```java @Primary @Component public class AudiCarService implements CarService { // 实现方法 } ``` 2. **在配置类的 @Bean 方法上标记** 适用于通过 Java 配置显式定义的 Bean: ```java @Configuration public class AppConfig { @Bean @Primary public CarService audiCarService() { return new AudiCarService(); } } ``` #### 三、常见问题及解决方案 1. **多个 Bean 标记了 @Primary** **问题**:如果多个同类型 Bean 都标记了 `@Primary`,Spring 仍会抛出 `NoUniqueBeanDefinitionException`。 **解决**:结合 `@Qualifier` 明确指定 Bean 名称: ```java @Autowired @Qualifier("specificBeanName") private CarService carService; ``` 2. **@Primary 与 @Qualifier 的优先级** **规则**:`@Qualifier` 的优先级高于 `@Primary`。如果同时存在,以 `@Qualifier` 指定的 Bean 为准[^3]。 3. **原型作用域(Prototype)下的行为** **注意**:若 Bean 的作用域为原型(`@Scope("prototype")`),每次注入时会创建新实例,但 `@Primary` 仍会生效,确保优先选择标记的 Bean。 #### 四、典型应用场景 1. **多实现类的默认注入** 例如,接口 `PaymentService` 有 `CreditCardPayment` 和 `PayPalPayment` 两个实现,若希望默认使用信用卡支付,可在 `CreditCardPayment` 类上添加 `@Primary`。 2. **环境切换(测试/生产)** 在测试环境中,可标记 Mock 实现为 `@Primary`,而在生产配置中替换为真实实现: ```java @Profile("test") @Primary @Component public class MockPaymentService implements PaymentService { // Mock 实现 } ``` 3. **避免显式指定 Bean 名称** 当不希望频繁使用 `@Qualifier` 时,`@Primary` 可简化代码。 #### 五、代码示例 ```java // 接口 public interface CarService { void drive(); } // 首选实现 @Primary @Component public class AudiCarService implements CarService { @Override public void drive() { System.out.println("Audi driving..."); } } // 其他实现 @Component public class BmwCarService implements CarService { @Override public void drive() { System.out.println("BMW driving..."); } } // 使用示例 @Service public class DriverService { @Autowired private CarService carService; // 自动注入 AudiCarService[^4] } ``` #### 六、与其他注解的对比 | 注解 | 作用 | 优先级 | |---------------|-------------------------------|--------| | `@Primary` | 标记默认首选 Bean | 低 | | `@Qualifier` | 按名称显式指定 Bean | 高 | | `@Conditional`| 根据条件动态注册 Bean | 独立 | §§ 1. `@Primary` 和 `@Qualifier` 在依赖注入中的区别是什么? 2. 如何在多环境配置中结合 `@Profile` 和 `@Primary`? 3. 如果多个 `@Primary` Bean 存在,如何调试 Spring 的注入行为? 4. `@Primary` 是否会影响 Bean 的生命周期或作用域?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值