美文网首页
spring @Bean的6个疑问

spring @Bean的6个疑问

作者: 饱饱想要灵感 | 来源:发表于2023-04-25 10:03 被阅读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类的实例。

    相关文章

      网友评论

          本文标题:spring @Bean的6个疑问

          本文链接:https://www.haomeiwen.com/subject/legpjdtx.html