Spring @Primary作用和实现原理

介绍

今天分享一下Spring中的@Primary注解,Primary的意思是主要的,我们在使用spring的时候,难免会定义多个类型相同的bean,这时候如果不采取一些方法,那么是无法正常使用bean的。

其实在刚开始使用spring的时候,一开始对于某些概念是很不清楚的,所以即使网上去找了很多答案,也是没有真正的理解,所以就导致很多东西都是似懂非懂,就比如根据类型和名称获取bean,一开始这个类型我是有点不太清楚的。

根据类型或者名称获取bean

根据名称获取bean这是很好理解的,在spring中,定义bean的方式有很多,不同通常都是@Component注解和@Bean注解来注册bean,使用@Component的时候我们可以指定名称,如果不指定,则就为类名的名称,只不过首字母小写,使用@Bean的时候,也可以指定,不指定的话则为方法名称,但是根据类型获取,之前不是很理解,其实类型就是接口,我们知道接口一般是不做任何实现的,由实现类来进行具体逻辑实现,可以有多个实现类,比如UserService接口有UserServiceImpl1和UserServiceImpl2两个实现类,那么我们就可以说UserServiceImpl1和UserServiceImpl2的类型是UserService,在spring中,这两个实现类如果定义成bean,那么都会被注册进spring IOC容器中,但是在获取的时候是有问题的。

byName

如果根据名称获取,那么是没问题的,因为注册进IOC容器时是注册了两个不同名称的bean,所以根据名称获取,只获取到了一个bean,所以能获取成功。

byType

如果根据类型获取,因为注册了两个bean,但是它们的类型是相同的,这时候直接根据类型获取,那么就会获取到两个bean,spring不能返回那个,所以就抛出异常。

No qualifying bean of type 'io.steakliu.spring.ioc.annotation.primary.PrimaryService' available: expected single matching bean but found 2: primaryServiceImpl1,primaryServiceImpl2
复制代码

解决方案

存在多个类型的bean时,可以通过@Qualifier注解指定名称,我们也可以在注入bean的时候指定具体的bean名称,不过这样的话就会变得很变扭,所以使用@Qualifier还是比较合理和规范,当然,也可以使用@Primary来,但实际上@Primary能解决的问题我觉得只是给了一个默认值,这样在获取bean的时候不会报错,当需要注入同一类型下的其他bean时,依旧需要指定名称。

实现原理

如果我们使用@Component或@Bean注解注册bean的时候,spring启动后会扫描工程路径下的包,然后找出相应的类,并解析相应的Bean,如果带有@Primary注解,那么就会将BeanDefinition的primary属性设置为true,然后将BeanDefinition注册到BeanFactory,如下所示。

在获取bean的时候,首先会获取类型下面的所有bean,然后再根据bean的名字去获取BeanDefination,最后选择primary属性为true的bean返回,如果同一类型下的bean都加了@Primary注解,那么获取的时候会报错。

以上就简单的分析了@Primary的源码,其实是比较简单的,primary作为bean定义信息中的一个属性,spring扫描到了标有这个注解,就会将BeanDefinition的primary设置为true,获取获取bean的时候,就再次取出Beandefinition,判断primary属性,然后从获取的候选bean中选出primary为true的那个。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Spring中的@Primary和@Qualifier是两个常用的注解,用于解决当有多个同类型的bean需要注入时的歧义问题。 @Primary注解用在bean的定义上,表示该bean是优先选择的bean。当有多个同类型的bean需要注入时,Spring会优先选择被@Primary注解标记的bean作为注入的对象。 @Qualifier注解用在注入点上,可以和@Autowired、@Resource等注解一起使用,用来指定具体要注入的bean的名称。通过在@Qualifier中指定bean的名称,可以明确告诉Spring要选择哪个bean进行注入。 举个例子来说明,假设有一个接口类型的bean,下面有两个实现类A和B都实现了这个接口,并且都被Spring管理。 当我们在其他地方需要注入这个接口类型的bean时,如果不使用@Qualifier和@PrimarySpring会产生歧义,无法确定注入哪个实现类的对象。 使用@Primary注解,我们可以在实现类A上标注@Primary,表示A是优先选择的bean。 当需要注入接口类型bean时,Spring会自动选择A作为注入的对象。 使用@Qualifier注解,我们可以在注入点上标注@Qualifier,然后在@Qualifier中指定具体要注入的bean的名称。 比如,可以使用@Qualifier("beanA")明确指定要注入的bean是A。 以上就是@Primary和@Qualifier的基本用法和含义,通过使用这两个注解可以很方便地解决多个同类型bean的注入问题。 ### 回答2: spring中的@Primary和@Qualifier是依赖注入中的两个注解。 @Primary注解用于标注一个类为首选的bean。当有多个类型相同的bean存在时,spring将会优先选择被@Primary注解标注的bean进行注入。 @Qualifier注解可以与@Autowired一起使用,用于解决存在多个类型相同的bean时的歧义性。通过为@Autowired指定@Qualifier注解的value属性,可以指定具体注入哪个bean。 例如,假设我们有一个接口Person,有两个实现类:Student和Teacher。如果我们在Spring配置文件中同时注册了这两个bean,那么在注入Person类型的依赖时就会有歧义。此时,我们可以使用@Primary注解为其中一个实现类标注为首选bean。这样,在需要注入Person类型的地方,spring就会优先选择被@Primary注解标注的实现类进行注入。 另一种情况是,如果我们不想使用@Primary注解来标注首选bean,而是希望根据特定的条件进行选择注入,就可以使用@Qualifier注解。@Qualifier注解需要与@Autowired注解一起使用,通过指定value属性来指定注入哪个bean。比如,我们可以在@Autowired注解后添加@Qualifier("student")来指定注入的是Student类型的bean。 通过@Primary和@Qualifier注解,我们可以在存在多个类型相同的bean时,精确控制注入的对象,避免歧义性。 ### 回答3: Spring是一个开源的Java框架,提供了依赖注入(Dependency Injection)的功能。在Spring中,我们可以使用@Primary和@Qualifier注解来处理多个相同类型的实例。 @Primary注解用于标识在多个相同类型的Bean中,哪个Bean应该作为首选的Bean。当我们不使用@Qualifier注解指定具体的Bean时,Spring会自动选择使用带有@Primary注解的Bean。例如,当我们有多个实现了同一个接口的类时,通过使用@Primary注解,我们可以指定一个类作为主要实现。 @Qualifier注解用于在多个相同类型的Bean中选择特定的Bean。当我们有多个相同类型的Bean需要注入时,在使用@Autowired或@Inject注入时,我们可以使用@Qualifier注解指定具体的Bean。@Qualifier注解的参数可以是Bean的名字或者是自定义的标识符。 举个例子来说,假设我们有一个接口Animal,有两个实现类Dog和Cat。如果我们希望将Cat作为首选的实现类,我们可以在Cat类上使用@Primary注解。如果有一个需要注入Animal类型的类,但我们想注入Dog,我们可以在注入的地方使用@Qualifier("dog")注解来指定具体的Bean。 总之,@Primary注解用于标识首选的Bean,@Qualifier注解用于指定特定的Bean。它们可以一起使用来处理多个相同类型的实例,使得依赖注入更加灵活和精确。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值