springboot 四层架构之间的关系整理笔记五

news2025/3/31 20:45:17

问题:service 和 多个serviceimpl 分层之间的逻辑关系?

好的!用班级活动的例子继续讲,假设班长(Service接口)要管理多种任务,而不同的班委(ServiceImpl实现类)负责不同场景的实现。这样分层后,代码会更灵活、易扩展!👇


场景设定

班级要组织一次 ‌「秋游活动」‌,班长(Service接口)定规则:

  • 必须有一个方法 planTrip() 用来规划路线
  • 必须有一个方法 calculateCost() 用来计算费用

但根据 ‌不同出行方式‌(比如步行、坐大巴),劳动委员和文艺委员分别写了两种实现!


1. Service接口(班长定的规则)

 

javaCopy Code

public interface TripService { String planTrip(); // 规划路线 double calculateCost(); // 计算费用 }


2. ServiceImpl实现类1:步行方案(劳动委员写的)

 

javaCopy Code

@Service("walkingTripService") // 给实现类起个名字,方便区分 public class WalkingTripServiceImpl implements TripService { @Override public String planTrip() { return "路线:学校 -> 公园(步行30分钟)"; } @Override public double calculateCost() { return 0; // 步行不需要费用 } }


3. ServiceImpl实现类2:大巴方案(文艺委员写的)

@Service("busTripService") public class BusTripServiceImpl implements TripService { @Override public String planTrip() { return "路线:学校 -> 山区(大巴1小时)"; } @Override public double calculateCost() { return 500; // 大巴租车费用 } }


关键问题:Controller 如何选择不同的实现?

就像班级要决定最终用哪种方案,可以通过两种方式:


方式1:用 @Qualifier 指定具体实现

在 Controller 中明确告诉 Spring 要注入哪个实现类:

@RestController

public class TripController {

@Autowired

@Qualifier("busTripService") // 指定用大巴方案

private TripService tripService;

@GetMapping("/plan") public String getPlan() { return tripService.planTrip(); } }


方式2:用 @Primary 标记默认实现

如果大部分情况用步行,可以设一个默认实现:

@Service("walkingTripService")

@Primary // 默认选这个 public class WalkingTripServiceImpl implements TripService { // ... 同上 }

Controller 中不指定时,自动用 @Primary 的实现:

@Autowired private TripService tripService; // 默认注入 WalkingTripServiceImpl


多个 ServiceImpl 的优势

就像班级可以灵活切换方案,代码也能动态调整!

  1. 按需切换‌:

    • 根据配置选择实现(比如测试环境用步行,生产环境用大巴)

    # application.yml school: trip-type: bus

  2. 扩展方便‌:

    • 如果新增「骑自行车」方案,只需写 BikeTripServiceImpl,其他代码不用改!
  3. 逻辑隔离‌:

    • 大巴的费用计算和步行完全不同,分开实现更清晰

实际应用场景

场景1:支付方式多样化
  • 接口:PaymentService
  • 实现类:
    • AliPayServiceImpl(支付宝)
    • WeChatPayServiceImpl(微信支付)
    • BankCardServiceImpl(银行卡)

Controller 根据用户选择调用不同实现:

// 根据用户选择的支付方式,动态注入对应的

ServiceImpl String paymentType = "wechat";

PaymentService paymentService = getPaymentService(paymentType); paymentService.pay(100);


场景2:数据库多版本支持
  • 接口:UserRepository
  • 实现类:
    • MySQLUserServiceImpl(连接 MySQL)
    • MongoDBUserServiceImpl(连接 MongoDB)

通过配置文件切换数据库:

yamlCopy Code

# application.yml database: type: mongodb


总结:Service 和多个 ServiceImpl 的关系就像「总规则和具体方案」

  • 📜 ‌Service接口‌:定义「必须做什么」(What)
  • 🛠 ‌ServiceImpl实现类‌:定义「具体怎么做」(How)
  • 🎛 ‌Controller‌:根据需求选择「用哪种实现」

这样设计后,班级活动(项目)既能保证统一规则,又能灵活适应各种变化! 🌟

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2323773.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

喜报|迪捷软件入选工信部“2024年信息技术应用创新解决方案”

为进一步深化行业信息技术应用创新,健全信息技术应用创新产业生态,加快新技术新产品应用推广,强化应用牵引和需求导向,加强区域联动和资源整合,工业和信息化部网络安全产业发展中心(工业和信息化部信息中心…

2.Python 计算机二级题库:选择题答案解析

一 对 题目1 题目2 题目3 补充:在 Python 中,数字类型的复数类型是 complex。 题目4 题目5 题目6 题目7 题目8 题目9 题目10 题目11 题目12 题目13 题目14 题目15 题目16 题目17 题目18 题目19 题目20 题目21 题目22 题目23 题目24 题目25 题目26 题目27…

使用Selenium和lxml库搜房网爬取某地区房屋信息(python、pycharm爬虫)

一、地址: url "https://zb.newhouse.fang.com/house/s/b91" # 第一页的 URL 但是这个爬虫我不知道为啥总是翻不了页数,请帮忙修改一下~ 二、用到的知识点以及代码详解: 这段代码是一个使用Selenium和lxml库实现的网页爬虫&a…

大模型训练过程中KVCache与MLA

基础内容 在Transformer模型中,每个token有qkv三个属性,分别通过神经网络变换得到。1 根据Transformer中注意力公式,每个token的q需要和之前所有的k计算注意力,然后经过Softmax函数后乘以之前所有token的V,得到最终的…

材质及制作笔记

基本流程: 建中模——zb雕刻高模——maya拓扑低模——拆uv——sp烘焙贴图——sp绘制材质——渲染 1 材质贴图: diffuse/albedo/basecolor:漫反射 reflection/specular:反射 metalness:金属度 glossiness&#xf…

语音机器人与智能体结合

自从春节期间deepseek的发布,大家对语音机器人接入大模型格外的关注。最近又收到一个需求,是语音机器人与智能体的结合。 什么是智能体? 智能体(Agent)是指能够感知环境并采取行动以实现目标的实体。根据其复杂程度&am…

Axios企业级封装实战:从拦截器到安全策略!!!

🚀 Axios企业级封装实战:从拦截器到安全策略 🔧 核心代码解析 // 创建Axios实例 const service axios.create({baseURL: api, // 🌐 全局API前缀timeout: 0, // ⏳ 永不超时(慎用!)withCrede…

Zerotier虚拟局域网在树莓派的应用和Syncthing配合Zerotier实现端到端文件同步

一、Zerotier的部署 1、官网注册账号 https://my.zerotier.com/i 2、选择linux系统,执行安装Zerotier curl -s https://install.zerotier.com | sudo bash3、将树莓派网络加入Zerotier zerotier-cli join DB62228FEDF6CE55DB62228FEDF6CE55 为你的Zerotier IP 需…

51c嵌入式~三极管~合集1

我自己的原文哦~ https://blog.51cto.com/whaosoft/12208603 一、PNP与NPN两种三极管使用方法 分享这篇文章总结下关于NPN和PNP两种型号三极管的使用和连接方法。 在单片机应用电路中三极管主要的作用就是开关作用。 PNP与NPN两种三极管使用方法 上图中,横向左…

SQL中累计求和与滑动求和函数sum() over()的用法

[TOC](SQL中累计求和与滑动求和函数sum() over()的用法) 一、窗口函数功能简介 sum(c) over(partition by a order by b) 按照一定规则汇总c的值,具体规则为以a分组,每组内按照b进行排序,汇总第一行至当前行的c的加和值。 sum()&#xff1a…

【Sql Server】在SQL Server中生成雪花ID(Snowflake ID)

大家好,我是全栈小5,欢迎来到《小5讲堂》。 这是《Sql Server》系列文章,每篇文章将以博主理解的角度展开讲解。 温馨提示:博主能力有限,理解水平有限,若有不对之处望指正! 目录 前言认识雪花ID…

FPGA——分秒计数器设计(DE2-115开发板)

一、项目创建 1.创建工程 点击File->New Project Wizard...或者直接在页面处点击 在第一行选择文件存放地点,第二行为项目名称,第三行为顶级设计实体名称 (下面的步骤可以暂时不做直接点Finish,因为是先写代码先把它跑出来暂…

雅思练习总结(九)

雅思练习总结(九) 本文章是雅思练习总结(九),总结了文章《BAKELITE》,内容包括原文精翻,文章脉络总结,单词扩展学习3个部分 1 文章原文及翻译 BAKELITE 翻译:贝克莱特…

windows USB 了解

GUID GUID 是一个 128 位的数字,在全球范围内是独一无二的,常被用于标识软件组件、设备接口等,以保证在不同系统和环境中能唯一识别特定对象。 DEFINE_GUID(GUID_DEVINTERFACE_USCUSTOMKEYS, 0x12345678, 0x1234, 0x5678, 0x12, 0x12, 0x23…

光谱相机的光谱信息获取

光谱信息的获取方式主要依赖于不同分光技术和成像方法,将入射光分解为不同波长并记录其强度。以下是常见的光谱信息获取技术分类及原理: ‌1. 分光技术(物理分解波长)‌ ‌(1) 滤光片法‌ ‌原理‌:使用固定或可调滤…

免去繁琐的手动埋点,Gin 框架可观测性最佳实践

作者:牧思 背景 在云原生时代的今天,Golang 编程语言越来越成为开发者们的首选,而对于 Golang 开发者来说,最著名的 Golang Web 框架莫过于 Gin [ 1] 框架了,Gin 框架作为 Golang 编程语言官方的推荐框架 [ 2] &…

构建大语言模型应用:简介(第一部分)

本专栏聚焦大语言模型(LLM)相关内容的解析,通过检索增强生成(RAG)应用的视角来进行。 本系列文章 简介(本文)数据准备句子转换器向量数据库搜索与检索大语言模型开源检索增强生成评估大语言模…

PEmicro Multilink FX调试踩坑

文章目录 1.背景2 功能说明2.1 实时数据查看功能2.1 电压观测2.2 SWO功能 3 设置与支持 1.背景 既然使用了NXP的芯片,笔者就想使用一下它的专用调试器,这里先说一下,笔者是从朋友那里借了一个调试器,型号为PEmicro Multilink FX …

主流大模型采用的架构、注意力机制、位置编码等汇总表

记录下主流大模型的一些核心知识点,包括: 架构注意力机制位置编码归一化激活函数模型参数 表中的一些模型已经是很久之前的了,比如表中并未收入 DeepSeek V3 中使用的MLA的注意力机制。先占个位,后续如果有更新的汇总表再来更…

SpringBoot学习笔记3.27

目录 实战篇第二课 1.注册参数的校验: 学习过程中遇到的问题: 1.什么是正则表达式 2.怎么自定义异常? 1. 创建全局异常处理类 2. 定义响应对象 3. 使用 ExceptionHandler 4. 设置响应状态码 5. 返回统一响应 6. 测试全局异常处理 …