spring @Primary-在spring中的使用方式

 更新时间:2022年01月25日 10:17:07   作者:qq_16055765  
这篇文章主要介绍了spring @Primary-在spring中的使用方式,具有很好的参考价值,希望对大家有所帮助。

spring @Primary在spring的使用

在spring 中使用注解,常使用@Autowired, 默认是根据类型Type来自动注入的。但有些特殊情况,对同一个接口,可能会有几种不同的实现类,而默认只会采取其中一种的情况下 @Primary 的作用就出来了。

下面是个简单的使用例子

有如下一个接口

public interface Singer {
    String sing(String lyrics);
}

有下面的两个实现类:

@Component // 加注解,让spring识别
public class MetalSinger implements Singer{
    @Override
    public String sing(String lyrics) {
        return "I am singing with DIO voice: "+lyrics;
    }
}
//注意,这里没有注解
public class OperaSinger implements Singer {
    @Override
    public String sing(String lyrics) {
        return "I am singing in Bocelli voice: "+lyrics;
    }
}

下面就是注入上面的

@Component
 public class SingerService {
        private static final Logger logger = LoggerFactory.getLogger(SingerService.class);
    @Autowired
    private Singer singer;
    public String sing(){
        return singer.sing("song lyrics");
    }
   }

I am singing with DIO voice: song lyrics. 原因很简单,就是 OperaSinger 这个类上面根本没有加上注解@Copmonent 或者 @Service, 所以spring 注入的时候,只能找到 MetalSinger 这个实现类. 所以才有这个结果。

但是如果一旦 OperaSinger 这个类加上了@Copmonent 或者 @Service 注解,有趣的事情就会发生,你会发现一个错误的结果或异常:

org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [main.service.Singer] is defined: expected single matching bean but found 2: metalSinger,operaSinger

提示很明确了,spring 根据类型无法选择到底注入哪一个。这个时候@Primay 可以闪亮登场了。

@Primary
@Component
public class OperaSinger implements Singer{
    @Override
    public String sing(String lyrics) {
        return "I am singing in Bocelli voice: "+lyrics;
    }
}

如果代码改成这样,再次运行,结果如下:

“I am singing in Bocelli voice: song lyrics”, 用@Primary 告诉spring 在犹豫的时候优先选择哪一个具体的实现。

用@Qualifier这个注解来解决问题

将上面的两个类改为如下:

@Component("metalSinger") // 加注解,让spring识别
public class MetalSinger implements Singer{
    @Override
    public String sing(String lyrics) {
        return "I am singing with DIO voice: "+lyrics;
    }
}
@Component("opreaSinger")
public class OperaSinger implements Singer {
    @Override
    public String sing(String lyrics) {
        return "I am singing in Bocelli voice: "+lyrics;
    }
}
@Component
public class SingerService {
    private static final Logger logger = LoggerFactory.getLogger(SingerService.class);
    @Autowired
    @Qualifier("opreaSinger")
    private Singer singer;
    public String sing(){
        return singer.sing("song lyrics");
    }
}

扩展:Spring注解常用汇总

使用注解之前要开启自动扫描功能

其中base-package为需要扫描的包(含子包)

<context:component-scan base-package=“cn.test”/>

@Configuration把一个类作为一个IoC容器,它的某个方法头上如果注册了@Bean,就会作为这个Spring容器中的Bean。

@Scope注解 作用域

  • @Lazy(true) 表示延迟初始化
  • @Service用于标注业务层组件、
  • @Controller用于标注控制层组件(如struts中的action)
  • @Repository用于标注数据访问组件,即DAO组件。
  • @Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
  • @Scope用于指定scope作用域的(用在类上)
  • @PostConstruct用于指定初始化方法(用在方法上)
  • @PreDestory用于指定销毁方法(用在方法上)
  • @Resource 默认按名称装配,当找不到与名称匹配的bean才会按类型装配。
  • @DependsOn定义Bean初始化及销毁时的顺序
  • @Primary自动装配时当出现多个Bean候选者时,被注解为@Primary的Bean将作为首选者,否则将抛出异常。(只对接口的多个实现生效)
  • @Autowired 默认按类型装配,如果我们想使用按名称装配,可以结合@Qualifier注解一起使用
  • @Autowired @Qualifier(“personDaoBean”) 存在多个实例配合使用

注解@Primary使用概述

在声明bean的时候,通过将其中一个可选的bean设置为首选

( primary) bean能够避免自动装配时的歧义性。

当遇到歧义性的时候, Spring将会使用首选的bean,而不是其他可选的bean。

实际上,你所声明就是“最喜欢”的bean。假设冰激凌就是你最喜欢的甜点。

在Spring中,可以通过@Primary来表达最喜欢的方案。

@Primary能够与@Component组合用在组件扫描的bean上,也可以与@Bean组合用在Java配置的bean声明中。

比如,下面的代码展现了如何将@Component注解的IceCream bean声明为首选的bean:

这里写图片描述

或者,如果你通过Java配置显式地声明IceCream,那么@Bean方法

应该如下所示:

这里写图片描述

如果你使用XML配置bean的话,同样可以实现这样的功能。

元素有一个primary属性用来指定首选的bean:

这里写图片描述

不管你采用什么方式来标示首选bean,效果都是一样的,都是告诉Spring在遇到歧义性的时候要选择首选的bean。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • SpringBoot整合BCrypt实现密码加密

    SpringBoot整合BCrypt实现密码加密

    这篇文章主要为大家详细介绍了SpringBoot整合BCrypt进行密码加密,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-11-11
  • Java的System.getProperty()方法获取大全

    Java的System.getProperty()方法获取大全

    这篇文章主要介绍了Java的System.getProperty()方法获取大全,罗列了System.getProperty()方法获取各类信息的用法,具有一定的参考借鉴价值,需要的朋友可以参考下
    2014-12-12
  • JAVA编程实现TCP网络通讯的方法示例

    JAVA编程实现TCP网络通讯的方法示例

    这篇文章主要介绍了JAVA编程实现TCP网络通讯的方法,简单说明了TCP通讯的原理并结合具体实例形式分析了java实现TCP通讯的步骤与相关操作技巧,需要的朋友可以参考下
    2017-08-08
  • Java基础教程之八大基本数据类型

    Java基础教程之八大基本数据类型

    这篇文章主要给大家介绍了关于Java基础教程之八大基本数据类型的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-06-06
  • Java接口异步调用优化技巧详解

    Java接口异步调用优化技巧详解

    本文详细介绍了在Java开发中,如何通过异步调用等技巧来优化接口的性能,有效避免阻塞和提高并发处理能力,提升系统的稳定性和响应速度
    2023-05-05
  • Java注解Annotation原理及自定义注解代码实例

    Java注解Annotation原理及自定义注解代码实例

    这篇文章主要介绍了Java注解Annotation原理及自定义注解代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-10-10
  • Java基于Servlet和JSP实现登录功能

    Java基于Servlet和JSP实现登录功能

    在 Web 开发中,用户登录功能是非常常见的模块之一,本文将通过使用 Java Servlet 和 JSP 实现一个简单的用户登录功能,展示如何创建登录页面、处理用户登录请求,并使用数据库验证用户信息,需要的朋友可以参考下
    2024-11-11
  • @WebFilter在SpringBoot无效的原因分析和解决方案

    @WebFilter在SpringBoot无效的原因分析和解决方案

    使用Ruoyi的demo部署成功后,发现js、css等静态文件都进入了过滤器,但是发现静态文件没有使用浏览器缓存,新建BrowserCacheFilter.java并增加@WebFilter处理,应用自动重启后发现@WebFilter无效,所以本文给大家介绍了@WebFilter在SpringBoot无效的原因分析和解决方案
    2024-03-03
  • java利用递归算法实现对文件夹的删除功能

    java利用递归算法实现对文件夹的删除功能

    这篇文章主要介绍了java利用递归算法实现对文件夹的删除功能,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-09-09
  • Java abstract class 与 interface对比

    Java abstract class 与 interface对比

    这篇文章主要介绍了 Java abstract class 与 interface对比的相关资料,需要的朋友可以参考下
    2016-12-12

最新评论