spring @Bean 参数注入规则- gpt4的回答

867 阅读3分钟

Q: 当前用@Bean声明bean时,其参数的注入规则是怎么样的,类型匹配优先?

如果有两个SellerRelationFacade类型的bean, 一个名字是sellerRelationFacade2, 另一个名字是sellerRelationFacade, 下面的方法会注入sellerRelationFacade还是sellerRelationFacade2

@Bean(name = "cspAccountAuthService")  
public CspAccountAuthService cspAccountAuthService(SellerRelationFacade sellerRelationFacade) { 
//初始化  
} 

A: 在Spring框架中,当使用方法参数自动注入时,Spring会默认按照类型进行匹配,如果找到多个相同类型的Bean,那么会按照Bean的名称进行匹配

在你给出的例子中,因为方法参数的名称是sellerRelationFacade,所以Spring会注入名为sellerRelationFacade的Bean,而不是名为sellerRelationFacade2的Bean。如果你想注入sellerRelationFacade2,你需要改变方法参数的名称或者使用@Qualifier注解明确指定Bean的名称,如下所示:

@Bean(name = "cspAccountAuthService")
public CspAccountAuthService cspAccountAuthService(@Qualifier("sellerRelationFacade2") SellerRelationFacade sellerRelationFacade) {
    //初始化
}

Q: 我想验证下这个注入规则,请给个例子,并给出依赖jar的gav

A: 要验证这个规则,你可以使用Spring框架的基本功能,所以你需要以下的依赖:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.3.10</version> <!-- 请根据实际情况使用最新的版本 -->
</dependency>

下面是一个简单的示例来验证这个规则:

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class Application {

    @Bean
    public String stringBean1() {
        return "Bean 1";
    }

    @Bean
    public String stringBean2() {
        return "Bean 2";
    }

    @Bean
    public MyService myService(String stringBean1) {
        return new MyService(stringBean1);
    }

    public static class MyService {
        private final String stringBean;

        public MyService(String stringBean) {
            this.stringBean = stringBean;
        }

        public String getStringBean() {
            return stringBean;
        }
    }

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Application.class);
        MyService myService = context.getBean(MyService.class);
        System.out.println(myService.getStringBean()); // 输出 "Bean 1"
    }
}

在这个例子中,MyService的构造函数需要一个类型为String的参数,Spring会发现有两个类型为String的Bean(stringBean1stringBean2),但是因为参数的名称是stringBean1,所以Spring会注入stringBean1这个Bean。当你运行这个程序,你会看到输出是"Bean 1",这验证了我们之前说的规则。

Q: 总结下spring的注入方式和注入规则

A: Spring框架提供了多种注入依赖的方式,包括:

  1. 基于构造函数的依赖注入:这种方式通过在Bean的构造函数中声明依赖,然后Spring会自动提供这些依赖。

  2. 基于Setter的依赖注入:这种方式通过Bean的Setter方法来注入依赖。

  3. 基于字段的依赖注入:这种方式直接在字段上使用@Autowired@Inject注解来注入依赖。

注入规则主要包括:

  1. 按类型匹配:默认的方式是按类型匹配,Spring会查找与声明的依赖类型相匹配的Bean。

  2. 按名称匹配:如果有多个相同类型的Bean,Spring会尝试按照Bean的名称进行匹配。例如在基于构造函数或Setter方法的依赖注入中,参数名称或Setter方法的名称会被用作Bean的名称。

  3. 使用@Qualifier注解:如果有多个相同类型的Bean,可以使用@Qualifier注解指定注入哪一个Bean,@Qualifier注解的参数就是Bean的名称。

  4. 使用@Primary注解:如果有多个相同类型的Bean,可以在其中一个Bean上使用@Primary注解,这样当Spring需要注入这种类型的Bean时,会优先选择标记为@Primary的Bean。

  5. 使用@Value注解:可以使用@Value注解来注入基本类型和String类型的值,这些值可以从属性文件中获取,也可以直接在注解中指定。

  6. 使用@Resource注解@Resource注解是JSR 250标准的一部分。它首先按名称进行匹配,如果没有找到匹配的Bean,然后再按类型进行匹配。

需要注意的是,避免在一个类中混合使用构造函数注入和Setter或字段注入,这可能导致混淆和不可预见的行为。通常推荐使用构造函数注入,因为它可以确保Bean的不变性和完整性。