spring @Bean的6个疑问

2023-04-25  本文已影响0人  饱饱抓住了灵感

在Spring Framework中,@Bean注解是用来将方法返回的对象作为spring容器中的一个bean进行注册的。

当我们在类上添加@Configuration注解时,Spring Framework会扫描带有@Bean注解的方法,并使用其返回的对象作为Bean,然后将其注册到Spring IoC容器中。这样,我们就可以在其他组件中通过注入的方式使用这些Bean。

@Bean注解还可以指定Bean的名称,scope以及依赖项等属性。

假设我们有一个类Person,它有一个属性name。 我们想要在Spring上下文中创建一个这样的对象。

public class Person {
    private String name;

    public Person(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

我们可以使用@Bean注解来定义这个类在Spring上下文中的实例化方法。

@Configuration
public class AppConfig {

    @Bean
    public Person person() {
        return new Person("John");
    }
}

我们可以使用@Autowired注解在其他类中引用这个对象。

@Service
public class GreetingService {

    @Autowired
    private Person person;

    public String sayHello() {
        return "Hello " + person.getName();
    }
}

在上面的例子中,我们使用了@Autowired注解来注入Person对象。Spring会自动将person()方法返回的对象注入到GreetingService类中的person字段中。

疑问一: @Bean是单例还是多例?

@Bean默认是单例。也可以通过在方法上添加@Scope注解来指定为多例。例如:

@Bean
@Scope("prototype")
public BeanClass beanClass() {
    return new BeanClass();
}

该@Bean方法返回的对象,每次在容器中请求时都会创建一个新的实例。如果没有指定@Scope,则默认为单例。在单例模式下,每次请求该Bean对象时都会返回同一个实例。

疑问二: 如果@Bean声明了多个Person怎么处理?

假设有两个不同的实现:

@Configuration
public class BeanConfig {
 
    @Bean(name="person1")
    public Person createPerson1() {
        return new Person("John", "Doe");
    }
 
    @Bean(name="person2")
    public Person createPerson2() {
        return new Person("Jane", "Doe");
    }
 
}

现在,可以通过两种方式使用它们。 第一种方式是使用bean名称注入它们,如下所示:

@Service
public class MyService {
 
    @Autowired
    @Qualifier("person1")
    private Person person1;
 
    @Autowired
    @Qualifier("person2")
    private Person person2;
 
    // ...
}

第二种方式是使用Spring Boot提供的List注入它们,如下所示:

@Service
public class MyService {
 
    @Autowired
    private List<Person> persons;
 
    // ...
}

此时,List将包含BeanConfig中声明的所有Person bean(在我们的示例中,person1和person2)。

疑问三: 依赖注入时, 如果没有使用@Qualifier会报错吗?

会报错。在使用@Bean声明多个同类型的实例时,如果需要在其他地方引用这些实例,需要使用@Qualifier指定要使用的实例的名称。如果没有使用@Qualifier,则默认使用与变量名称相同的实例。如果找不到与变量名称相同的实例,则会抛出NoSuchBeanDefinitionException异常。

疑问四: 如果多个Person的@Bean没有指定名称会报错吗?

是的,如果没有指定名称,Spring容器将无法区分它们,并且会抛出异常。在这种情况下,可以使用@Qualifier注释并指定Bean的名称,以便Spring容器可以正确地注入Bean。

疑问五: 如果多个Person的@Bean指定了相同的名称会怎么样?

如果多个Person的@Bean指定了相同的名称, 后面的会覆盖掉先前定义的一个Person。如果要避免这种情况,可以使用@Primary注解标记其中一个Person bean 作为默认先选项,或者为每个bean提供一个唯一的名称。

疑问六: @Primary是干嘛的?

@Primary是一个标记注解,与@Bean注解一起使用,用于指示在自动装配相同类型的bean时应该优先选择哪个bean。

例如,如果有多个实现了某个接口的bean,并在另一个bean上声明了@Autowired注解以自动装配该接口类型的bean,则可以使用@Primary注解指定在自动装配期间应该首选哪个bean。

示例代码:

@Component
@Primary
public class A implements MyInterface {
    // ...
}

@Component
public class B implements MyInterface {
    // ...
}

@Component
public class C {
    @Autowired
    private MyInterface myInterface;

    // ...
}

在上面的例子中,使用@Primary注解标记bean A是首选实现MyInterface接口的bean,所以在C类中自动装配MyInterface接口时,将优先选择A类的实例。

上一篇 下一篇

猜你喜欢

热点阅读