spring的@primary和@qualifier注解解决一个接口多个实现的注入问题

本文深入解析Spring框架中@Primary和@Qualifier注解的作用与应用场景,包括解决实现类冲突及模块间解耦问题。

@Primary注解

Spring中有提供一个@Primary注解,具体的作用是在一个接口有多个实现类的情况下,会默认选择其中一种实现,帮助Spring对象的正常注入。

比如说现在有一个接口UserService,它有两个实现类UserServiceImpl1和UserServiceImpl2,根据依赖倒置的原则,在Spring中注入的对象应该是接口,由接口去调用具体的实现。

// 接口
public interface UserService {
    String getUserName();
}
// 实现1
@Service("userServiceImpl1")
public class UserServiceImpl1 implements UserService{
    public String getUserName() {
        return "张三";
    }
}
// 实现2
@Service("userServiceImpl2")
public class UserServiceImpl1 implements UserService {
    public String getUserName() {
        return "李四";
    }
}
// 调用者注入接口对象
@Service("loginServiceImpl")
public class LoginServiceImpl implements LoginService {
    @Autowired
    private userService; // 通过接口注入实现

    public void getLoginUser() {
        System.out.pringln("当前登录的用户是:" + userSerivce.getUserName());
    }
}

那么现在就有一个问题,因为Spring注入对象的时候默认是根据类型Type来自动注入的,在有两个实现的情况下,Spring无法根据类型选择到底注入哪一个,即接口不知道该调用哪个实现,就会产生检查异常,导致编译不通过。这时候就可以用@Primary来解决这个问题。

// 实现2
@Primary
@Service("userServiceImpl2")
public class UserServiceImpl1 implements UserService {
    public String getUserName() {
        return "李四";
    }
}

用@Primary注解来告诉Spring在不知道该选哪一个具体实现的时候选哪一个。

这个注解可以用在模块拆分的场景。比如说有一个模块A,有一个模块B,模块A和模块B之间通过接口模块进行交互。通过在接口模块中定义接口,模块B实现这个接口,模块A调用这个接口(注入)。这时候,如果把B模块要拆掉不要,那么A模块中注入的时候就找不到具体的实现,就会报检查异常。这时候,可以在接口模块中添加默认实现类,然后在B模块的真正实现类上添加@Primary注解,那么当有B模块的时候就会调用B模块中的实现,没有的话就调用接口模块中的默认实现,也就实现了模块之间的解耦。

@Qualifier注解

Spring也提供一个@Qualifier注解来解决实现冲突的问题。

// 实现1
@Service("userServiceImpl1")
@Qualifier("userServiceImpl1")
public class UserServiceImpl1 implements UserService{
    public String getUserName() {
        return "张三";
    }
}
// 实现2
@Service("userServiceImpl2")
@Qualifier("userServiceImpl2")
public class UserServiceImpl1 implements UserService {
    public String getUserName() {
        return "李四";
    }
}
// 调用者注入接口对象
@Service("loginServiceImpl")
public class LoginServiceImpl implements LoginService {
    @Autowired
    @Qualifier("userServiceImpl2")
    private userService; // 通过接口注入实现
    
    public void getLoginUser() {
        System.out.pringln("当前登录的用户是:" + userSerivce.getUserName());
    }
}

通过在实现类和注入调用上使用@Qualifier注解可以调用到具体实现,相当于一种标识机制。

 

"一个人的成长,是从发现自己并没有自己想象的那么重要开始的。"

转载于:https://www.cnblogs.com/yanggb/p/10842827.html

`@Primary` 注解可以与 `@Qualifier` 注解配合使用。这两个注解Spring 中用于解决依赖注入时的歧义问题,但它们的侧重点不同。`@Primary` 用于指定默认的首选 Bean,在存在多个同类型的 Bean 可供注入时,Spring 会优先选择被 `@Primary` 注解标记的 Bean;而 `@Qualifier` 则用于显式指定要注入的 Bean 的名称或标识符,提供了更精确的控制 [^1][^2][^3]。 在实际使用中,如果同时使用了 `@Primary` `@Qualifier`,`@Qualifier` 的优先级更高。也就是说,当通过 `@Qualifier` 显式指定了要注入的 Bean 名称时,Spring 会忽略 `@Primary` 注解,直接使用 `@Qualifier` 指定的 Bean [^2]。 以下是一个示例代码,展示了 `@Primary` 注解与 `@Qualifier` 注解的配合使用: ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Primary; import org.springframework.stereotype.Component; // 定义一个接口 interface PaymentService { void pay(); } // 实现类 1,标记为 @Primary @Component @Primary class CreditCardPaymentService implements PaymentService { @Override public void pay() { System.out.println("Paying with credit card"); } } // 实现类 2 @Component class PayPalPaymentService implements PaymentService { @Override public void pay() { System.out.println("Paying with PayPal"); } } // 使用 @Autowired @Qualifier 注入指定的 Bean @Component class PaymentProcessor { @Autowired @Qualifier("payPalPaymentService") private PaymentService paymentService; public void processPayment() { paymentService.pay(); } } ``` 在上述示例中,`CreditCardPaymentService` 被标记为 `@Primary`,表示它是默认的 `PaymentService` 实现。但在 `PaymentProcessor` 类中,通过 `@Qualifier("payPalPaymentService")` 显式指定了要注入的 Bean 为 `PayPalPaymentService`,因此在调用 `processPayment` 方法时,会使用 `PayPalPaymentService` 进行支付。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值