关于Qualifier你要知道的二三事

@Qualifier注解的作用-定义Bean-指定Bean的名称

@Qualifier注解可以区分具有相同类型的多个Bean,用于明确指定要注入的Bean的名称或限定符。通过为要注入的Bean添加 @Qualifier注解,你可以告诉Spring应该使用哪个Bean,以解决Spring框架中依赖注入时的歧义性问题。

假设我们有一个名为"UserService"的服务接口,有多个实现类可以用于不同的业务逻辑。现在,我们需要在另一个类中注入"UserService",但由于有多个实现类可用,我们需要明确指定要注入的具体实现类。

示例代码如下:

public interface UserService {
    void performAction();
}

@Component
@Qualifier("implementationA")
public class UserServiceImplA implements UserService {
    public void performAction() {
        System.out.println("Performing action with UserServiceImplA");
    }
}

@Component
@Qualifier("implementationB")
public class UserServiceImplB implements UserService {
    public void performAction() {
        System.out.println("Performing action with UserServiceImplB");
    }
}

@Component
public class UserClient {
    @Autowired
    @Qualifier("implementationA")
    private UserService userService;

    public void doSomething() {
        userService.performAction();
    }
}

错误的案例:

@Component
public class UserClient {
    @Autowired
    private UserService userService;

    public void doSomething() {
        userService.performAction();
    }
}

明确:@Autowired注解是按照类型注入Bean。由于UserServiceImplA、UserServiceImplB都是实现自接口UserService,因此在Spring注入过程中,会导致Spring不知道该注入哪个Bean的实现。 注入时,如果不使用该注解,会报以下的异常:

关于Qualifier你要知道的二三事_第1张图片

NoUniqueBeanDefinitionException异常是Spring框架中的一个异常,它表示在自动装配(Autowired)过程中无法确定要注入的bean,因为有多个符合条件的bean可用。

在上面的示例中,我们定义了一个"UserService"接口,并有两个实现类"UserServiceImplA"和"UserServiceImplB"。在"UserClient"类中,我们使用@Autowired注解注入"UserService"接口,并使用@Qualifier注解标记要注入的具体实现类。

通过@Qualifier(“implementationA”),我们明确指定了要注入的是"UserServiceImplA"实现类。这样,当"UserClient"类中使用"userService"时,将调用"UserServiceImplA"的实现方法。

通过@Qualifier注解,我们能够精确选择要注入的特定Bean,解决了存在多个相同类型的Bean时的歧义问题。

同类型的Bean注入知识拓展

如果存在多个Bean,它们具有相同的类型但不同的名称,那么在注入这些Bean时不会抛出NoUniqueBeanDefinitionException异常。相反,Spring会根据类型进行自动装配,选择与目标类型匹配的Bean进行注入。

以下是一个示例,演示具有相同类型但不同名称的多个Bean的自动装配:

@Component("userService")
public class UserService {
    public void performAction() {
        System.out.println("Performing action in UserService");
    }
}

@Component("adminService")
public class AdminService {
    public void performAction() {
        System.out.println("Performing action in AdminService");
    }
}

现在,我们可以在另一个类中使用@Autowired注解来注入这两个Bean:

@Component
public class ServiceClient {
    @Autowired
    private UserService userService;

    @Autowired
    private AdminService adminService;

    public void performServiceAction() {
        userService.performAction();
        adminService.performAction();
    }
}

在上述示例中,ServiceClient类成功地注入了UserService和AdminService两个不同名称但相同类型的Bean,因为它们都是被@Component注解标记的Spring管理的Bean。

总结起来,当存在具有相同类型但不同名称的多个Bean时,Spring可以根据类型进行自动装配,选择合适的Bean进行注入,而不会抛出异常。只有当存在多个相同类型的Bean且没有提供明确的标识符时,才会抛出NoUniqueBeanDefinitionException异常。

@Qualifier注解的作用-注入Bean-配合@Configuration使用

当在一个业务Bean中存在多个同类型的Bean时,可以使用@Qualifier注解来指定要注入的具体Bean。

@Configuration
public class AppConfig {

    @Bean
    @Qualifier("database")
    public DataSource dataSource() {
        // 返回一个数据库数据源的实现
        return new DatabaseDataSource();
    }

    @Bean
    @Qualifier("file")
    public DataSource fileDataSource() {
        // 返回一个文件数据源的实现
        return new FileDataSource();
    }

    @Bean
    public DataProcessor dataProcessor(@Qualifier("database") DataSource dataSource) {
        // 通过@Qualifier注解指定要注入的数据源为"database"
        return new DataProcessor(dataSource);
    }
}
public interface DataSource {
    void connect();
    void disconnect();
}

public class DatabaseDataSource implements DataSource {
    @Override
    public void connect() {
        System.out.println("Connecting to the database...");
        // 连接数据库的具体实现逻辑
    }

    @Override
    public void disconnect() {
        System.out.println("Disconnecting from the database...");
        // 断开数据库连接的具体实现逻辑
    }
}

public class FileDataSource implements DataSource {
    @Override
    public void connect() {
        System.out.println("Connecting to the file system...");
        // 连接文件系统的具体实现逻辑
    }

    @Override
    public void disconnect() {
        System.out.println("Disconnecting from the file system...");
        // 断开文件系统连接的具体实现逻辑
    }
}

在上面的例子中,通过@Configuration注解标记了一个配置类AppConfig。在该配置类中定义了两个名为dataSource和fileDataSource的Bean方法,并分别使用@Qualifier注解指定了它们的限定符为"database"和"file"。

接着,在dataProcessor方法上,使用@Qualifier(“database”)注解来指定要注入的数据源为名为"database"的Bean。这样,在其他地方使用@Autowired或@Inject注解注入DataProcessor时,就会根据@Qualifier注解指定的限定符来选择正确的Bean进行注入。

总结

由此可见,关于 @Qualifier注解,在Spring中的主要作用有两个:

  • 在定义Bean的地方,使用@Qualifier注解为Bean添加一个限定符,这个限定符可以是任何字符串,用于区分同一类型的多个Bean。
@Bean
@Qualifier("database")
public DataSource dataSource() {
    // 返回一个数据库数据源的实现
    return new DatabaseDataSource();
}
  • 在需要进行注入Bean的地方,使用@Qualifier注解并指定相同的限定符值,具体来说,假设有两个名为"databaseDataSource"和"fileDataSource"的DataSource类型的Bean,并且它们都使用了@Qualifier注解并指定了不同的限定符值。
@Autowired
@Qualifier("database")
private DataSource dataSource;

从源码中看@Qualifier注解

内容待完善中…

写在最后

感谢您读到这里,如果觉得文章写的还不错或有任何疑问,可以添加我微信,我随时为您解答。

你可能感兴趣的:(Spring,Cloud,笔记,java,开发语言,spring,boot,团队开发)