0


【Spring面试全家桶】@Primary注解你真的会用吗

文章目录

@Primary注解是Spring Framework中的一个注解,用于标记具有多个实例的Bean的主要实例。以下是关于@Primary注解的知识点:

  1. @Primary注解的作用:@Primary注解用于标记具有相同类型的多个实例中的主要实例。当一个Bean需要注入这种类型的Bean时,Spring会注入使用@Primary注解标记的主要实例。
  2. @Primary注解的使用:在一个有多个实例的Bean中使用@Primary注解来标记主要实例。可以通过在Bean的类定义或构造函数参数中添加@Primary注解来使用它。
  3. @Primary注解的优先级:当一个类中有多个具有相同类型的Bean时,可以使用@Primary注解设置主要实例。主要实例优先于其他实例被注入。如果没有使用@Primary注解,则最后一个装配的Bean会被注入。
  4. @Primary注解的局限性:@Primary注解只适用于Bean的类型,不能用于Bean的名称。因此,如果有多个同一类型的Bean,但它们需要以不同的名称被注入,则无法使用@Primary来确定主要实例。
  5. @Qualifier和@Primary注解的区别:@Primary注解用于标记具有相同类型的多个实例中的主要实例。而@Qualifier注解用于标记具有特定名称的Bean,以便在多个具有相同类型的Bean中选择特定的实例。 总之,@Primary注解是Spring Framework中的一个重要注解,用于标记具有多个实例的Bean的主要实例。它可以帮助解决多个同一类型的Bean被注入时的问题。

@Primary注解的作用

@Primary是一个Spring Framework的注解,用于标记一个bean(组件)是首选的bean(组件)。当多个相同类型的bean被定义时,被标记为@Primary的bean会被优先选择。该注解可以用于以下场景中:

  1. 当有多个同类型的bean时,注入第一个:例如,一个Spring应用程序中可能有多个名为“datasource”的DataSource实例,但应用程序可能需要使用其中一个特定的实例作为首选DataSource。可以通过在此标有@Primary注解的bean上使用@Autowired注解来指示Spring将此bean注入到所有需要Datasource依赖项的组件中。
  2. 当使用@Configuration注释的配置类时,作为默认bean:在使用@Configuration配置类时,可以将@Primary注解用于其中一个bean,以指示Spring在主配置类中定义的bean和其他@Configuration配置类中定义的bean之间选择该bean。

示例:

publicinterfacePaymentService{voidpay();}@Service@PrimarypublicclassAliPaymentServiceImplimplementsPaymentService{@Overridepublicvoidpay(){System.out.println("使用阿里支付");}}@ServicepublicclassWxPaymentServiceImplimplementsPaymentService{@Overridepublicvoidpay(){System.out.println("使用微信支付");}}@AutowiredprivatePaymentService paymentService;

在这个例子中,我们定义了两个PaymentService的实现类,AliPaymentServiceImpl上应用了@Primary注解,表示它是优先选择的实现类。在使用@Autowired注入PaymentService的时候,Spring 会自动选择AliPaymentServiceImpl这个类。如果没有使用@Primary,会抛出NoUniqueBeanDefinitionException。

总之,@Primary注解是一个非常有用的注解,它可以让开发人员在多个同类型的bean中选择一个首选bean,避免了在使用注入时出现歧义的问题。

@Primary注解的使用

@Primary注解是Spring框架中的一个重要注解之一,用来标识一个bean是首选的(primary),在使用自动装配(auto-wiring)时,如果存在多个类型(type)相同的bean,Spring会优先选择标记为@Primary的bean进行注入。下面详细介绍@Primary注解的常见使用与高级用法。

1. 常见使用

@Primary注解常见使用场景如下:

1.1 在单个配置类中标记@Primary

在Spring配置类中,通过@Bean注解定义多个相同类型的bean时,可以使用@Primary注解标记一个首选的bean,例如:

@ConfigurationpublicclassAppConfig{@BeanpublicDataSourcedataSource(){// ...}@Primary// 标记为首选bean@Bean("mySqlDataSource")publicDataSourcemySqlDataSource(){// ...}@Bean("oracleDataSource")publicDataSourceoracleDataSource(){// ...}}

在上述配置中,如果需要注入DataSource,由于存在两个DataSource类型的bean,Spring会优先选择@Primary注解标记的mySqlDataSource。

1.2 在单个@Service、@Controller等注解的类中标记@Primary

在@Service、@Controller等注解的类中,如果存在多个相同类型的bean,也可以使用@Primary注解标记一个首选的bean,例如:

@Service@Primary// 标记为首选beanpublicclassSomeServiceAimplementsSomeService{// ...}@ServicepublicclassSomeServiceBimplementsSomeService{// ...}

在上述配置中,如果需要注入SomeService,由于存在两个SomeService类型的bean,Spring会优先选择标记为@Primary的SomeServiceA。

2. 高级用法

除了常见使用场景,@Primary注解还有一些高级用法,如下:

2.1 使用@Qualifier与@Primary组合

@Qualifier注解是Spring提供的注解之一,用于指定一个特定的bean,例如:

@ComponentpublicclassSomeComponent{@Autowired@Qualifier("mySqlDataSource")privateDataSource dataSource;// ...}

在上述代码中,@Qualifier(“mySqlDataSource”)指定了需要注入的bean名称为mySqlDataSource的DataSource。然而,如果存在多个类型为DataSource的bean,这种方式可能会出现歧义,因此可以与@Primary注解组合使用,例如:

@ConfigurationpublicclassAppConfig{@Bean@Primary// 标记为首选bean@Qualifier("mySqlDataSource")publicDataSourcemySqlDataSource(){// ...}@Bean@Qualifier("oracleDataSource")publicDataSourceoracleDataSource(){// ...}}

在上述配置中,指定@Qualifier(“mySqlDataSource”)时,由于存在两个DataSource类型的bean,但是标记为@Primary的mySqlDataSource会被优先选择。

2.2 使用@ConditionalOnMissingBean与@Primary组合

@ConditionalOnMissingBean注解是Spring提供的注解之一,用于判断当前上下文中是否存在指定类型(type)的bean,如果不存在,则创建一个新的bean。与@Primary注解结合使用时,可以在不存在指定类型的bean时创建标记为@Primary的bean,例如:

@ConfigurationpublicclassAppConfig{@Bean@Primary// 标记为首选bean@ConditionalOnMissingBean// 如果不存在 DataSource 类型的bean,则创建一个新的publicDataSourcedataSource(){// ...}}

在上述配置中,如果当前上下文中不存在DataSource类型的bean,会创建标记为@Primary的dataSource,否则,已存在的bean会被优先选择。

3. 总结

@Primary注解是Spring框架中的一个重要注解,用来标识一个bean是首选的,在使用自动装配时,如果存在多个类型相同的bean,Spring会优先选择标记为@Primary的bean进行注入。除了常见使用场景外,@Primary注解还有一些高级用法,如与@Qualifier和@ConditionalOnMissingBean注解组合使用。在实际开发中,开发者可根据实际需求,选择合适的使用方式。

@Primary注解的优先级

@Primary注解是Spring框架提供的一个用于解决依赖注入歧义的注解。在一个类(或者一个接口)有多个实现类的情况下,@Primary注解可以指定其中一种实现类作为Spring容器中被注入的主要实现类。在使用@Autowired或者@Qualifier注入Bean时,如果没有指定具体的名称,那么Spring容器将会优先选择使用带有@Primary注解的Bean。

@Primary注解的优先级如下:

  1. @Primary注解具有最高优先级。如果一个类同时标注了@Primary注解和@Qualifier注解,那么@Primary注解会覆盖@Qualifier注解。
  2. @Primary注解作用于Bean的定义层(即在@Configuration或者@Component注解的类中定义的Bean),而不是作用于Bean的使用层。这意味着在使用@Autowired或者@Qualifier注解进行注入时,如果有多个同类型的Bean都标注了@Primary注解,那么Spring容器将会使用最先加载的那个@Primary注解的Bean进行注入。
  3. 如果在使用@Autowired或者@Qualifier注解时,没有特别指定Bean的名称或者类型,那么Spring容器会使用带有@Primary注解的Bean进行注入。

总的来说,@Primary注解可以非常方便地解决多个同类型Bean的注入问题,并且具有最高优先级,使用起来非常简单。但是需要注意的是,在使用@Primary注解时,一定要确保它标注的是正确的主要Bean,否则可能会引发一些意料之外的问题。

@Primary注解的局限性

@Primary注解是Spring框架中的一个非常常用的注解,主要用于在多个相同类型的bean中指定默认的实现。然而,@Primary注解也存在一些局限性,具体如下:

  1. 只能指定一个默认实现:@Primary注解只能用来指定一个默认实现,如果有多个实现,只能有一个默认实现。如果需要指定多个默认实现,则需要使用其他的方式,比如使用@Qualifier注解。
  2. 不可以与@Autowired注解同时使用:当我们使用@Primary注解指定默认实现时,如果需要在代码中注入bean实例,不可以使用@Autowired注解,因为这会导致Spring无法确定应该注入哪个bean实例。此时,我们需要使用@Qualifier注解来指定具体的bean实例。
  3. 无法应对特殊情况:虽然@Primary注解可以用来指定默认实现,但是在一些特殊情况下可能会失效,比如当我们在使用Spring的Profile功能时,如果针对不同的Profile配置了不同的bean实现,那么@Primary注解指定的默认实现可能会失效,此时我们需要使用其他方式来指定默认实现。

因此,虽然@Primary注解非常方便,但是在一些特殊情况下可能无法满足需求,需要使用其他方式来指定bean实现。

@Qualifier和@Primary注解的区别

在Spring框架中,@Qualifier和@Primary注解都是用来解决依赖注入中多个同类型Bean的问题,它们的功能略有不同。

@Qualifier注解是通过指定Bean的名称来指定注入哪个Bean,它可以和@Autowired或@Inject一起使用。如果存在多个同类型的Bean时,通过添加@Qualifier注解来指定需要注入的Bean,如下面的例子所示:

@ComponentpublicclassClassA{...}@ComponentpublicclassClassB{...}@ComponentpublicclassClassC{@Autowired@Qualifier("ClassA")privateClassA classA;@Autowired@Qualifier("ClassB")privateClassB classB;...}

在上面的例子中,通过@Qualifier注解指定了需要注入的ClassA和ClassB。

@Primary注解是用来标记一个Bean为首选的Bean,当存在多个同类型的Bean时,会自动选择被@Primary标记的Bean注入,如下面的例子所示:

@Component@PrimarypublicclassClassA{...}@ComponentpublicclassClassB{...}@ComponentpublicclassClassC{@AutowiredprivateClassA classA;@AutowiredprivateClassB classB;...}

在上面的例子中,ClassA被标记为@Primary,当注入ClassC中的classA时,会自动选择被标记为@Primary的ClassA注入。如果没有被标记为@Primary的Bean,则会报错。

总之,@Qualifier注解是用来指定具体的Bean名称来注入的;@Primary注解是用来标记一个首选的Bean,当存在多个同类型的Bean时,在没有指定具体注入哪个Bean时,会首先注入被标记为@Primary的Bean。

@Primary注解的底层工作原理

@Primary注解是Spring Framework中的一个注解,用于标记一个Bean作为默认Bean,在出现多个同类型的Bean时,优先使用被@Primary注解标记的Bean。

@Primary注解的底层工作原理可以分为以下几个步骤:

1.在BeanDefinition中注册Bean时,如果该Bean被@Primary注解标记,则会在BeanDefinition中添加一个primary属性,表示该Bean是默认Bean。

2.当Spring容器需要获取某个类型的Bean时,会先判断是否有该类型的@Primary注解标记的Bean,如果有,则直接使用该Bean。

3.如果没有@Primary注解标记的Bean,则会选择一个BeanDefinition中primary属性为true的Bean作为默认Bean。

4.如果BeanDefinition中没有primary属性为true的Bean,则会选择一个名称最小的Bean作为默认Bean。

总之,@Primary注解是通过标记BeanDefinition中的primary属性来实现的,而选择默认Bean则是通过选择具有primary属性的Bean或名称最小的Bean来实现的。在多个同类型的Bean中使用@Primary注解可以让我们更方便地控制默认Bean的选择,方便我们实现业务逻辑。

@Primary注解实战问题与解决方案

@Primary注解是Spring Framework提供的一种用于注入Bean的方式,它的作用是当有多个相同类型的Bean时,优先使用被@Primary注解的Bean。在实际开发中,经常会遇到使用@Primary注解的问题,下面介绍一些实战问题与解决方案。

问题一:多个同类型的Bean,如何确定哪个Bean被@Primary注解?

解决方案:在Spring容器启动时,会扫描所有被@Bean注解的方法,并将返回的对象作为Bean放入容器中。如果有多个同类型的Bean,需要在其中一个添加@Primary注解,表示优先使用该Bean。当需要使用该类型的Bean时,Spring Framework会自动选择@Primary注解的Bean。如果想要查看哪个Bean被@Primary注解,可以使用以下方法:

@AutowiredpublicvoidsetBeans(List<TypeOfBean> beans){for(TypeOfBean bean : beans){if(bean.getClass().isAnnotationPresent(Primary.class)){System.out.println(bean.getClass().getName()+" is @Primary");}}}

该方法会自动查找所有类型为TypeOfBean的Bean,打印出被@Primary注解的Bean。

问题二:如何在不影响原有@Primary注解的前提下,指定使用其他Bean?

解决方案:在某些情况下,我们需要使用非@Primary注解的Bean,而不是默认的@Primary注解的Bean。可以使用@Qualifier注解指定使用哪个Bean。@Qualifier注解需要与@Autowired注解一起使用,如下所示:

@Autowired@Qualifier("beanName")privateTypeOfBean bean;

其中,beanName为要使用Bean的名称。

问题三:如何在测试代码中使用不同的Bean?

解决方案:在测试代码中,与业务代码不同的是,我们可以使用不同的配置文件或者配置类进行测试,以达到使用不同的Bean的目的。可以通过在测试类中添加@ActiveProfiles注解,并指定使用的配置文件或配置类来实现。如下所示:

@SpringBootTest@ActiveProfiles("test")publicclassTestClass{...}

在这个例子中,我们可以在test配置文件中设置优先使用哪个Bean,或者在TestConfig配置类中设置优先使用哪个Bean。

以上是使用@Primary注解的一些实战问题与解决方案,希望能对您有所帮助。

标签: spring 面试 java

本文转载自: https://blog.csdn.net/java_wxid/article/details/131341255
版权归原作者 我是廖志伟 所有, 如有侵权,请联系我们删除。

“【Spring面试全家桶】@Primary注解你真的会用吗”的评论:

还没有评论