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(stringBean1和stringBean2),但是因为参数的名称是stringBean1,所以Spring会注入stringBean1这个Bean。当你运行这个程序,你会看到输出是"Bean 1",这验证了我们之前说的规则。
Q: 总结下spring的注入方式和注入规则
A: Spring框架提供了多种注入依赖的方式,包括:
-
基于构造函数的依赖注入:这种方式通过在Bean的构造函数中声明依赖,然后Spring会自动提供这些依赖。
-
基于Setter的依赖注入:这种方式通过Bean的Setter方法来注入依赖。
-
基于字段的依赖注入:这种方式直接在字段上使用
@Autowired或@Inject注解来注入依赖。
注入规则主要包括:
-
按类型匹配:默认的方式是按类型匹配,Spring会查找与声明的依赖类型相匹配的Bean。
-
按名称匹配:如果有多个相同类型的Bean,Spring会尝试按照Bean的名称进行匹配。例如在基于构造函数或Setter方法的依赖注入中,参数名称或Setter方法的名称会被用作Bean的名称。
-
使用@Qualifier注解:如果有多个相同类型的Bean,可以使用
@Qualifier注解指定注入哪一个Bean,@Qualifier注解的参数就是Bean的名称。 -
使用@Primary注解:如果有多个相同类型的Bean,可以在其中一个Bean上使用
@Primary注解,这样当Spring需要注入这种类型的Bean时,会优先选择标记为@Primary的Bean。 -
使用@Value注解:可以使用
@Value注解来注入基本类型和String类型的值,这些值可以从属性文件中获取,也可以直接在注解中指定。 -
使用@Resource注解:
@Resource注解是JSR 250标准的一部分。它首先按名称进行匹配,如果没有找到匹配的Bean,然后再按类型进行匹配。
需要注意的是,避免在一个类中混合使用构造函数注入和Setter或字段注入,这可能导致混淆和不可预见的行为。通常推荐使用构造函数注入,因为它可以确保Bean的不变性和完整性。