栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring(SpringBoot)--同类型多个bean的注入--@Primary/@Qualifier

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring(SpringBoot)--同类型多个bean的注入--@Primary/@Qualifier

原文网址:Spring(SpringBoot)--同类型多个bean的注入--@Primary/@Qualifier_IT利刃出鞘的博客-CSDN博客

简介

本文用示例介绍Spring中某个接口有多个实现类时该如何注入。

问题复现

需求:一个支付接口,有两个实现:支付宝支付、微信支付。想调用支付宝支付方法。

接口

package com.knife.tmp;

public interface Pay {
    void doPay();
}

实现

支付宝

package com.knife.tmp.impl;

import com.knife.tmp.Pay;
import org.springframework.stereotype.Component;


@Component
public class AlipayImpl implements Pay {
    @Override
    public void doPay() {
        System.out.println("支付宝支付");
    }
}

微信支付

package com.knife.tmp.impl;

import com.knife.tmp.Pay;
import org.springframework.stereotype.Component;


@Component
public class WeChatImpl implements Pay {
    @Override
    public void doPay() {
        System.out.println("微信支付");
    }
}

Controller

package com.knife.controller;

import com.knife.tmp.Pay;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class PayController {
    @Autowired
    private Pay pay;

    @GetMapping("/pay")
    public String pay() {
        pay.doPay();
        return "test success";
    }
}

测试

首先,还没运行,就可以看到Idea红色波浪线提示:

运行结果:

Description:

Field pay in com.knife.controller.PayController required a single bean, but 2 were found:
    - alipayImpl: defined in file [E:workIdea_projdemo_Simpledemo_SpringBoottargetclassescomknifetmpimplAlipayImpl.class]
    - weChatImpl: defined in file [E:workIdea_projdemo_Simpledemo_SpringBoottargetclassescomknifetmpimplWeChatImpl.class]


Action:

Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed

如下图:

原因分析

        @Autowired是通过类型来注入的。以上边的示例来说,@Autowired注入一个Pay接口,此时Spring会查找所有实现了Pay接口的bean,此时发现了两个:AlipayImpl,WeChatImpl,然后就会报错。

解决方案1:@Primary

说明

        将@Primary放到接口的某个实现类上边。这样如果此接口有多个实现类,则会注入有@Primary的实现类。

实例

相对于“问题复现”,只修改支付宝实现类,在上边添加@Primary,如下:

package com.knife.tmp.impl;

import com.knife.tmp.Pay;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Component;


@Primary
@Component
public class AlipayImpl implements Pay {
    @Override
    public void doPay() {
        System.out.println("支付宝支付");
    }
}

这样Controller就不会再有红色波浪线:

运行结果

启动成功。

访问:http://localhost:8080/pay

后端结果

解决方案2:value属性 +@Qualifier

说明

        在接口的某个实现类上边的@Component里指定value,例如:@Component("xxx"),使用@Autowired注入的地方用@Qualifier("xxx")来指定(xxx表示@Component里的value)。这样如果此接口有多个实现类,则会注入@Qualifier("xxx")指定的实现类。

实例

接口

package com.knife.tmp;

public interface Pay {
    void doPay();
}

支付宝实现类

package com.knife.tmp.impl;

import com.knife.tmp.Pay;
import org.springframework.stereotype.Component;


@Component("alipay")
public class AlipayImpl implements Pay {
    @Override
    public void doPay() {
        System.out.println("支付宝支付");
    }
}

微信支付实现类

package com.knife.tmp.impl;

import com.knife.tmp.Pay;
import org.springframework.stereotype.Component;


@Component("wechat")
public class WeChatImpl implements Pay {
    @Override
    public void doPay() {
        System.out.println("微信支付");
    }
}

Controller

package com.knife.controller;

import com.knife.tmp.Pay;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class PayController {
    @Qualifier("alipay")
    @Autowired
    private Pay pay;

    @GetMapping("/pay")
    public String pay() {
        pay.doPay();
        return "test success";
    }
}

测试

启动成功。

访问:http://localhost:8080/pay

后端结果

解决方案3:指定属性名(不推荐)

说明

        @Autowired提供这样的规则,首先它会根据类型找到对应的Bean,如果对应类型的Bean不是唯一的,那么它会根据其属性名称和Bean的名称进行匹配。如果匹配得上,就会使用该Bean;如果还无法匹配,就会抛出异常。

        所以,在注入的地方,将属性名设置成与bean名字一样即可。

实例

接口

package com.knife.tmp;

public interface Pay {
    void doPay();
}

支付宝实现

package com.knife.tmp.impl;

import com.knife.tmp.Pay;
import org.springframework.stereotype.Component;


@Component
public class AlipayImpl implements Pay {
    @Override
    public void doPay() {
        System.out.println("支付宝支付");
    }
}

微信支付

package com.knife.tmp.impl;

import com.knife.tmp.Pay;
import org.springframework.stereotype.Component;


@Component
public class WeChatImpl implements Pay {
    @Override
    public void doPay() {
        System.out.println("微信支付");
    }
}

Controller

package com.knife.controller;

import com.knife.tmp.Pay;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class PayController {
    @Autowired
    private Pay alipay;

    @GetMapping("/pay")
    public String pay() {
        alipay.doPay();
        return "test success";
    }
}

测试

启动成功。

访问:http://localhost:8080/pay

结果:

后端结果

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/855488.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号