51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

Spring Bean 的命名

1、概览 {#1概览}

当有多个相同类型的实现时,需要对 Spring Bean 进行不同的命名。这是因为如果 Bean 没有唯一的名称,Spring 在注入 Bean 时会出现歧义。

通过控制 Bean 的命名,可以告诉 Spring 我们想将哪个 Bean 注入到目标对象中。

本文将带你了解 Spring Bean 命名策略,以及如何为同一类型的 Bean 赋予多个名称。

2、默认 Bean 命名策略 {#2默认-bean-命名策略}

Spring 为创建 Bean 提供了多种注解,可以在不同的级别使用。例如,可以在 Bean 类上放置一些注解,在创建 Bean 的方法上放置另一些注解。

首先,来看看 Spring 的默认命名策略。当只指定注解而不指定任何值时,Spring 是如何命名 Bean 的?

2.1、类级注解 {#21类级注解}

首先从在类级别使用的注解的默认命名策略开始。Spring 会使用类名为 Bean 命名,并将第一个字母转换为小写。

举个例子:

@Service
public class LoggingService {
}

如上,Spring 为 LoggingService 类创建了一个 Bean,并使用 loggingService 名称进行了注册。

这种默认的命名策略适用于所有用于创建 Spring Bean 的类级别注解,例如 @Component@Service@Controller

2.2、方法级注解 {#22方法级注解}

Spring 提供了 @Bean@Qualifier 等注解,可用于创建 Bean 的方法。

让我们通过一个示例来了解 @Bean 注解的默认命名策略:

@Configuration
public class AuditConfiguration {
    @Bean
    public AuditService audit() {
          return new AuditService();
    }
}

在这个配置类中,Spring 以 audit 为名注册了一个 AuditService 类型的 Bean。当在方法上使用 @Bean 注解时,Spring 会将方法名用作 Bean 名。

还可以在方法上使用 @Qualifier 注解,如下。

3、自定义 Bean 的命名 {#3自定义-bean-的命名}

当需要在同一个 Spring Context 中创建多个相同类型的 Bean 时,可以为 Bean 自定义名称,并使用这些名称来引用它们。

来看看如何为 Spring Bean 自定义名称:

@Component("myBean")
public class MyCustomComponent {
}

这一次,Spring 将创建 MyCustomComponent 类型的 Bean,并命名为 myBean

由于我们显式地给 Bean 赋予了名称,Spring 将使用这个名称,然后就可以用它来引用或访问 Bean 了。

@Component("myBean") 类似,也可以使用 @Service("myService")@Controller("myController")@Bean("myCustomBean") 等其他注解指定名称,然后 Spring 将以给定的名称注册 Bean。

4、使用 @Bean 和 @Qualifier 命名 Bean {#4使用-bean-和-qualifier-命名-bean}

4.1、@Bean 的 value 值 {#41bean-的-value-值}

如前所述,@Bean 注解应用于方法级别,默认情况下,Spring 将方法名称用作 Bean 名称。

这个默认的 Bean 名称可以被覆盖 - 可以使用 @Bean 注解来指定值。

@Configuration
public class MyConfiguration {
    @Bean("beanComponent")
    public MyCustomComponent myComponent() {
        return new MyCustomComponent();
    }
}

此时,当我们要获取 MyCustomComponent 类型的 Bean 时,可以使用 beanComponent 这个名称来引用该 Bean。

Spring @Bean 注解通常在配置类方法中声明。它可以通过直接调用同一类中的其他 @Bean 方法来引用它们。

4.2、@Qualifier 的 value 值 {#42qualifier-的-value-值}

还可以使用 @Qualifier 注解来命名 Bean。

首先,创建一个接口 Animal,它将会由多个类实现:

public interface Animal {
    String name();
}

现在,定义一个实现类 Cat,并为其添加 @Qualifier 注解,其 value 值为 cat

@Component 
@Qualifier("cat") 
public class Cat implements Animal { 
    @Override 
     public String name() { 
        return "Cat"; 
     } 
}

再添加一个 Animal 的实现 Dog,并用 value 值为 dog@Qualifier 对其进行注解:

@Component
@Qualifier("dog")
public class Dog implements Animal {
    @Override
    public String name() {
        return "Dog";
    }
}

现在,编写一个 PetShow 类,在其中注入两个不同的 Animal 实例:

@Service 
public class PetShow { 
    private final Animal dog; 
    private final Animal cat; 

    public PetShow (@Qualifier("dog")Animal dog, @Qualifier("cat")Animal cat) { 
      this.dog = dog; 
      this.cat = cat; 
    }
    public Animal getDog() { 
      return dog; 
    }
    public Animal getCat() { 
      return cat; 
    }
}

PetShow 类中,通过在构造函数参数上使用 @Qualifier 注解,并在每个注解的 value 属性中使用限定的 Bean 名称,注入了 Animal 类型的两个实现。每当我们使用该限定名称时,Spring 就会将具有该限定名称的 Bean 注入到目标 Bean 中。

5、验证 Bean 名称 {#5验证-bean-名称}

到目前为止,我们已经看到了为 Spring Bean 命名的不同示例。现在的问题是,我们如何验证或测试这一点?

可以通过一个单元测试来验证这种行为:

@ExtendWith(SpringExtension.class)
public class SpringBeanNamingUnitTest {
    private AnnotationConfigApplicationContext context;
    
    @BeforeEach
    void setUp() {
        context = new AnnotationConfigApplicationContext();
        context.scan("com.baeldung.springbean.naming");
        context.refresh();
    }
    
    @Test
    void givenMultipleImplementationsOfAnimal_whenFieldIsInjectedWithQualifiedName_thenTheSpecificBeanShouldGetInjected() {
        PetShow petShow = (PetShow) context.getBean("petShow");
        assertThat(petShow.getCat().getClass()).isEqualTo(Cat.class);
        assertThat(petShow.getDog().getClass()).isEqualTo(Dog.class);
    }

在此 JUnit 测试中,在 setUp 方法中初始化了 AnnotationConfigApplicationContext,该方法用于获取 Bean。

然后,只需使用标准断言验证 Spring Bean 的类。

6、总结 {#6总结}

本文介绍了 Spring 中 Bean 默认的命令策略,以及如何自定义 Bean 的命名。还介绍了如何为同一类型的 Bean 赋予多个名称。


Ref:https://www.baeldung.com/spring-bean-names

赞(1)
未经允许不得转载:工具盒子 » Spring Bean 的命名