IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> SpringBoot根据配置注入接口的不同实现类 -> 正文阅读

[Java知识库]SpringBoot根据配置注入接口的不同实现类

一.引言

我们在使用springboot进行开发的时候经常用到@Autowired@Resource进行依赖注入,但是当我们一个接口对应多个不同的实现类的时候如果不进行一下配置项目启动时就会报错,那么怎么根据不同的需求注入不同的类型就是一个值得考虑的问题,虽然@Autowired@Resource就可以实现,但是我们也可以选择更加灵活的@ConditionalOnProperty注解来实现

二.代码演示

1.问题描述

TestController.java

package com.example.demo.controller;

import com.example.demo.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @ClassName TestController
 * @Author xuwei
 * @DATE 2022/6/28
 */
@RestController
@RequestMapping("test")
public class TestController {

    //注入需要的service
    @Autowired
    TestService testService;

    @RequestMapping("test")
    public void test(){
        testService.sayHello();
    }
}

?TestService.java

package com.example.demo.service;

/**
 * @InterfaceName TestService
 * @Author xuwei
 * @DATE 2022/6/28
 */
public interface TestService {
    /**
     * sayHello方法
     */
    void sayHello();
}

TestService实现类一??TestServiceImplOne.java

package com.example.demo.service.impl;

import com.example.demo.service.TestService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @ClassName TestServiceImplOne
 * @Author xuwei
 * @DATE 2022/6/28
 */
@Service
public class TestServiceImplOne implements TestService {
    private static final Logger LOGGER = LoggerFactory.getLogger(TestServiceImplOne.class);
    /**
     * sayHello方法
     */
    @Override
    public void sayHello() {
        LOGGER.info("I am TestServiceImplOne");
    }
}

TestService实现类二?TestServiceImplTwo.java

package com.example.demo.service.impl;

import com.example.demo.service.TestService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @ClassName TestServiceImplTwo
 * @Author xuwei
 * @DATE 2022/6/28
 */
@Service
public class TestServiceImplTwo implements TestService {
    private static final Logger LOGGER = LoggerFactory.getLogger(TestServiceImplTwo.class);
    /**
     * sayHello方法
     */
    @Override
    public void sayHello() {
        LOGGER.info("I am TestServiceImplTwo");
    }
}

这时我们的程序启动会报错,大概意思就是找到了两个实现类

***************************
APPLICATION FAILED TO START
***************************

Description:

Field testService in com.example.demo.controller.TestController required a single bean, but 2 were found:
	- testServiceImplOne: defined in file [/Users/xuwei/Desktop/Projects/IdeaProjects/demo/target/classes/com/example/demo/service/impl/TestServiceImplOne.class]
	- testServiceImplTwo: defined in file [/Users/xuwei/Desktop/Projects/IdeaProjects/demo/target/classes/com/example/demo/service/impl/TestServiceImplTwo.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

2.解决方案

2.1使用@Autowired的时候将接口变量名改为实现类的限定名

TestController.java修改为如下

package com.example.demo.controller;

import com.example.demo.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @ClassName TestController
 * @Author xuwei
 * @DATE 2022/6/28
 */
@RestController
@RequestMapping("test")
public class TestController {

    //修改变量名为实现类的限定名
    @Autowired
    TestService testServiceImplOne;

    @RequestMapping("test")
    public void test(){
        testServiceImplOne.sayHello();
    }
}

我们可以将接口的命名改为对应实现类的限定名,默认为类名且首字母小写,当然我们也可以自己给接口的实现类配置限定名,例如@Service("serviceOne") 之后在引用时使用我们配置的限定名,这样程序都可以自动找到实现类,测试结果如下:

2.2 使用@Autowired配合@Qualifier指定限定名注入实现类

其实这个方法的原理和上面的很相似,@Autowired会默认根据type进行注入,如果type相同会根据id进行注入,也就是我们说的限定名,我们只需要让它找到对应限定名的类即可,上面我们通过修改接口变量名的方式来实现,同时我们还可以配合@Qualifier注解来实现相同的目的

TestController.java修改为如下

package com.example.demo.controller;

import com.example.demo.service.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @ClassName TestController
 * @Author xuwei
 * @DATE 2022/6/28
 */
@RestController
@RequestMapping("test")
public class TestController {

    //配合注解指定限定名
    @Qualifier("testServiceImplTwo")
    @Autowired
    TestService testService;

    @RequestMapping("test")
    public void test(){
        testService.sayHello();
    }
}

当然,和上一种方法相同,我们注解中填的值是实现类的限定名,可以使用默认,也可以和上面一样在使用@Service时进行配置,测试结果如下:

2.3@ConditionalOnProperty

以上两种方法都是硬编码方式,在我们需要进行用户配置时很不方便,所以我们可以使用@ConditionalOnProperty注解来实现配置文件控制的功能

在TestController中使用@Resource注入

package com.example.demo.controller;

import com.example.demo.service.TestService;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

/**
 * @ClassName TestController
 * @Author xuwei
 * @DATE 2022/6/28
 */
@RestController
@RequestMapping("test")
public class TestController {

    //使用@Resource注入
    @Resource
    TestService testService;

    @RequestMapping("test")
    public void test(){
        testService.sayHello();
    }
}

TestServiceImplOne.java

package com.example.demo.service.impl;

import com.example.demo.service.TestService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;

/**
 * @ClassName TestServiceImplOne
 * @Author xuwei
 * @DATE 2022/6/28
 */
@Component
@ConditionalOnProperty(name = "serviceControl",havingValue = "serviceOne")
public class TestServiceImplOne implements TestService {
    private static final Logger LOGGER = LoggerFactory.getLogger(TestServiceImplOne.class);
    /**
     * sayHello方法
     */
    @Override
    public void sayHello() {
        LOGGER.info("I am TestServiceImplOne");
    }
}

TestServiceImplTwo.java

package com.example.demo.service.impl;

import com.example.demo.service.TestService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;

/**
 * @ClassName TestServiceImplTwo
 * @Author xuwei
 * @DATE 2022/6/28
 */
@Component
@ConditionalOnProperty(name = "serviceControl",havingValue = "serviceTwo")
public class TestServiceImplTwo implements TestService {
    private static final Logger LOGGER = LoggerFactory.getLogger(TestServiceImplTwo.class);
    /**
     * sayHello方法
     */
    @Override
    public void sayHello() {
        LOGGER.info("I am TestServiceImplTwo");
    }
}

在配置文件中配置我们使用的类

测试结果如下?

?三.总结

前两种方法都是去寻找接口的限定名,第三种方法中@ConditionalOnProperty(name = "serviceControl",havingValue = "serviceOne")注解的name属性对应配置文件中的key值,而havingValue属性对应的是配置文件中我们上面定义的name属性对应的value值

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-07-03 10:36:15  更:2022-07-03 10:37:44 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 16:37:52-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码