spring中service层是干嘛的

news2024/11/14 2:57:01

在Spring框架中,Service层是一个非常重要的组成部分,主要用于实现和封装应用程序的业务逻辑。以下是Service层的主要职责和特点:

主要职责

  1. 实现业务逻辑

    • Service层包含了应用程序的核心业务逻辑。例如,处理用户的注册、登录、订单生成等操作。
    • 这些业务逻辑通常涉及多个数据操作,Service层负责协调这些操作,确保业务逻辑的完整性和一致性。
  2. 事务管理

    • Service层通常负责管理事务,确保一系列数据库操作要么全部成功,要么全部失败。Spring提供了声明式事务管理,通过注解(如@Transactional)可以轻松地管理事务。
  3. 数据验证

    • 在进行业务操作之前,Service层可以对输入数据进行验证,确保数据的有效性和合法性。
  4. 调用数据访问层

    • Service层通常会调用DAO(Data Access Object)或Repository层的方法来执行具体的数据库操作。通过这种方式,Service层将业务逻辑与数据访问逻辑分离,提高了代码的可维护性和可测试性。
  5. 提供对外的API

    • Service层可以提供对外的服务接口,这些接口可以被Controller层调用,从而实现业务逻辑的封装和重用。

特点

  1. 解耦

    • Service层通过依赖注入(DI)与DAO层和Controller层解耦,使得各个层之间的依赖关系更加清晰,便于维护和扩展。
  2. 复用

    • Service层的方法可以被多个Controller方法调用,实现了业务逻辑的复用,避免了代码重复。
  3. 可测试性

    • Service层通常是一个独立的单元,可以很容易地编写单元测试来验证业务逻辑的正确性。
  4. 事务边界

    • Service层通常是事务的边界,事务管理通常在这个层进行配置,确保业务操作的原子性。

示例

以下是一个简单的Service层示例,展示了如何实现用户注册的业务逻辑:

@Service
@Transactional
public class UserService {

    @Autowired
    private UserRepository userRepository;

    /**
     * 用户注册
     * @param user 用户对象
     * @return 注册成功的用户对象
     */
    public User register(User user) {
        // 1. 验证用户输入
        if (user == null || user.getUsername() == null || user.getPassword() == null) {
            throw new IllegalArgumentException("Invalid user information");
        }

        // 2. 检查用户名是否已存在
        if (userRepository.findByUsername(user.getUsername()) != null) {
            throw new RuntimeException("Username already exists");
        }

        // 3. 加密密码
        String encryptedPassword = DigestUtils.md5DigestAsHex(user.getPassword().getBytes());
        user.setPassword(encryptedPassword);

        // 4. 保存用户到数据库
        return userRepository.save(user);
    }
}

总结

Service层在Spring框架中起到了连接Controller层和DAO层的桥梁作用,负责处理核心的业务逻辑,管理事务,验证数据,并提供可复用的服务接口。通过合理的分层设计,可以显著提高应用程序的可维护性和可扩展性。

@Transactional

是Spring框架提供的一个注解,用于声明式事务管理。它可以帮助开发者更方便地管理和控制事务,确保在执行数据库操作时,多个操作要么全部成功,要么全部失败,从而保证数据的一致性和完整性。以下是 @Transactional 注解的主要作用和使用方法:

主要作用

  1. 事务管理

    • @Transactional 注解可以应用于方法或类上,用于标记该方法或类中的所有方法需要在一个事务中执行。
    • 当方法被调用时,Spring会自动开启一个事务,并在方法执行完毕后根据结果提交或回滚事务。
  2. 保证数据一致性

    • 在执行多个数据库操作时,如果其中一个操作失败,事务会回滚,撤销所有已经执行的操作,确保数据的一致性。
    • 例如,在一个转账操作中,如果从账户A扣款成功,但在向账户B存款时失败,事务会回滚,撤销从账户A扣款的操作。
  3. 异常处理

    • 如果方法执行过程中抛出未捕获的异常,默认情况下事务会回滚。可以通过配置 @Transactional 注解来指定哪些异常会导致事务回滚,哪些异常不会导致事务回滚。

使用方法

1. 应用于方法上
@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    @Transactional
    public void transferMoney(Long fromUserId, Long toUserId, double amount) {
        // 从fromUserId账户扣款
        User fromUser = userRepository.findById(fromUserId).orElseThrow(() -> new RuntimeException("User not found"));
        fromUser.setBalance(fromUser.getBalance() - amount);
        userRepository.save(fromUser);

        // 向toUserId账户存款
        User toUser = userRepository.findById(toUserId).orElseThrow(() -> new RuntimeException("User not found"));
        toUser.setBalance(toUser.getBalance() + amount);
        userRepository.save(toUser);
    }
}
2. 应用于类上
@Service
@Transactional
public class UserService {

    @Autowired
    private UserRepository userRepository;

    public void transferMoney(Long fromUserId, Long toUserId, double amount) {
        // 从fromUserId账户扣款
        User fromUser = userRepository.findById(fromUserId).orElseThrow(() -> new RuntimeException("User not found"));
        fromUser.setBalance(fromUser.getBalance() - amount);
        userRepository.save(fromUser);

        // 向toUserId账户存款
        User toUser = userRepository.findById(toUserId).orElseThrow(() -> new RuntimeException("User not found"));
        toUser.setBalance(toUser.getBalance() + amount);
        userRepository.save(toUser);
    }
}

配置选项

@Transactional 注解提供了多个属性,用于进一步控制事务的行为:

  • propagation:事务传播行为,默认值为 REQUIRED,表示如果有事务则加入当前事务,否则新建一个事务。
  • isolation:事务隔离级别,默认值为 DEFAULT,表示使用数据库的默认隔离级别。
  • readOnly:是否只读事务,默认值为 false,表示读写事务。
  • timeout:事务超时时间,默认值为 -1,表示使用全局事务超时时间。
  • rollbackFor:指定哪些异常会导致事务回滚,默认情况下运行时异常(RuntimeException)会导致事务回滚。
  • noRollbackFor:指定哪些异常不会导致事务回滚。

示例

@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, readOnly = false, timeout = 30, rollbackFor = Exception.class)
    public void transferMoney(Long fromUserId, Long toUserId, double amount) {
        // 从fromUserId账户扣款
        User fromUser = userRepository.findById(fromUserId).orElseThrow(() -> new RuntimeException("User not found"));
        fromUser.setBalance(fromUser.getBalance() - amount);
        userRepository.save(fromUser);

        // 向toUserId账户存款
        User toUser = userRepository.findById(toUserId).orElseThrow(() -> new RuntimeException("User not found"));
        toUser.setBalance(toUser.getBalance() + amount);
        userRepository.save(toUser);
    }
}

总结

@Transactional 注解是Spring框架中用于声明式事务管理的重要工具。通过在方法或类上添加 @Transactional 注解,可以轻松地控制事务的行为,确保数据库操作的原子性和一致性。这不仅简化了事务管理的代码,也提高了应用程序的可靠性和可维护性。

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

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

相关文章

linux网络的基本设置

1、查看网络接口信息 ip a/ip addr #简略的查看网络接口信息 ifconfig #只显示当前活跃的设备 ifconfig -a #实现当前主机的所有网络设备&#xff0c;包括未运行的设备 rootubuntu1:~# ifconfig ens33:flags4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 设备名…

利用AI制作《职业生涯规划PPT》,10分钟完成

职业生涯规划是大学生活中非常重要的一环。通过制定职业规划&#xff0c;你能够明确未来的职业目标、认清自身的优劣势&#xff0c;进而制定切实可行的计划&#xff0c;以便顺利踏上职业发展的道路。而制作一份精美的职业生涯规划PPT&#xff0c;能有效帮助你在面试、职业规划报…

【数据结构与算法】希尔排序(直接插入排序)

大家好&#xff0c;我是小卡皮巴拉 文章目录 目录 引言 一.直接插入排序的基本思想 二. 直接插入排序算法解析 详细版本的算法思想解析 算法思想提炼 实现代码 画图刨析 三. 直接插入排序的特性 复杂度分析 稳定性分析 四. 希尔排序的基本思想 五. 希尔排序算法解…

RK3568 Android12跳过认证 预置谷歌服务GMS

在Rom开发中需要发布海外版本时基本都需要内置google服务,而规范方式集成的话都需要设备进行认证,获取google应用签名等非常复杂的一套流程,一般大厂才有这些资质和资源,这里介绍一种非常规方式集成GMS,跳过设置认证流程,在RK3568 android12环境亲测有效。 谷歌全家桶中…

深度学习之卷积问题

1 卷积在图像中有什么直观作用 ​ 在卷积神经网络中&#xff0c;卷积常用来提取图像的特征&#xff0c;但不同层次的卷积操作提取到的特征类型是不相同的&#xff0c;特征类型粗分如表1所示。 ​ 表1 卷积提取的特征类型 卷积层次特征类型浅层卷积边缘特征中层卷积局部特征深…

Go语言的内置容器

文章目录 一、数组数组的定义数组声明数组特点数组元素修改 二、切片切片声明基于数组创建切片使用make()函数构造切片使用append()为切片动态添加元素\使用copy()复制新的切片数组与切片相互转换 三、Map映射Map定义使用make()函数创建map用切片作为map的值使用delete()函数删…

二叉树的各种操作补充

二叉树的各种操作补充 求二叉树的结点数求二叉树的叶结点数求二叉树的高度求二叉树的第k层结点数查找指定结点层序遍历判断二叉树是否是完全二叉树 我们任然沿用二叉树的基本信息&#xff1a; typedef char BTDataType; typedef struct BinaryTreeNode {BTDataType _data;struc…

Go语言的常用内置函数

文章目录 一、Strings包字符串处理包定义Strings包的基本用法Strconv包中常用函数 二、Time包三、Math包math包概述使用math包 四、随机数包&#xff08;rand&#xff09; 一、Strings包 字符串处理包定义 Strings包简介&#xff1a; 一般编程语言包含的字符串处理库功能区别…

Perfetto中如何使用SQL语句

在使用 Perfetto 分析 Android 性能时&#xff0c;可以通过 Perfetto 提供的内置 SQL 查询来提取和分析不同的性能数据。Perfetto 允许你在 UI 界面或命令行中运行 SQL 查询&#xff0c;提取出 Trace 数据中包含的各种性能信息&#xff0c;比如 CPU 使用率、线程状态、内存分配…

QML项目实战:自定义TextField

目录 一.添加模块 import QtQuick.Controls 1.2 import QtQuick.Controls.Styles 1.4 import QtGraphicalEffects 1.15 二.自定义TextField 1.属性设置 2.输入框设置 3.按钮开关 三.效果 1.readonly为false 2.readonly为true 四.代码 一.添加模块 import QtQuick.…

【进阶】Stable Diffusion 插件 Controlnet 安装使用教程(图像精准控制)

Stable Diffusion WebUI 的绘画插件 Controlnet 最近更新了 V1.1 版本&#xff0c;发布了 14 个优化模型&#xff0c;并新增了多个预处理器&#xff0c;让它的功能比之前更加好用了&#xff0c;最近几天又连续更新了 3 个新 Reference 预处理器&#xff0c;可以直接根据图像生产…

DAF-FM DA与NO反应后,生成的产物能够发出强烈的绿色荧光,254109-22-3

一、基本信息 产品名称&#xff1a;DAF-FM DA&#xff08;一氧化氮NO荧光探针DAF-FM&#xff09; 英文名称&#xff1a;DAF-FM DA&#xff0c;DAF-FM diacetate CAS号&#xff1a;254109-22-3 分子式&#xff1a;C25H18F2N2O7 供应商&#xff1a;陕西新研博美生物科技 分…

在 Mac 和 Windows 系统中快速部署 OceanBase

OceanBase 是一款分布式数据库&#xff0c;具备出色的性能和高扩展性&#xff0c;可以为企业用户构建稳定可靠、灵活扩展性能的数据库服务。本文以开发者们普遍熟悉的Windows 或 Mac 环境为例&#xff0c;介绍如何快速上手并体验OceanBase。 一、环境准备 1. 硬件准备 OceanB…

使用Ant Design的Layout布局不能撑满整个屏幕问题解决方法

代码示例&#xff1a; import React, { useState } from react import {LaptopOutlined,NotificationOutlined,UserOutlined, } from ant-design/icons import type { MenuProps } from antd import { Layout, Menu, theme } from antd import routes from ./routes/index imp…

【ubuntu18.04】使用U盘制作ubuntu18.04启动盘操作说明

打开show application 打开Startup Disk 选择镜像 双击选择ubuntu的iso镜像 镜像下载地址 Ubuntu 18.04.6 LTS (Bionic Beaver) 制作镜像 注意&#xff1a; 制作镜像会格式化U盘&#xff0c;记得备份资料 点击Make Startup Disk,弹出如下对话框 点击Yes 输入管理员密码&a…

22.04Ubuntu---ROS2创建python节点

创建工作空间 mkdir -p 02_ros_ws/src 然后cd到该目录 创建功能包 在这条命令里&#xff0c;tom就是你的功能包 ros2 pkg create tom --build-type ament_python --dependencies rclpy 可以看到tom功能包已经被创建成功了。 使用tree命令&#xff0c;得到如下文件结构 此时…

《手写Spring渐进式源码实践》实践笔记(第十七章 数据类型转换)

文章目录 第十七章 数据类型转换工厂设计实现背景技术背景Spring数据转换实现方式类型转换器&#xff08;Converter&#xff09;接口设计实现 业务背景 目标设计实现代码结构类图实现步骤 测试事先准备属性配置文件转换器工厂Bean测试用例测试结果&#xff1a; 总结 第十七章 数…

使用docker形式部署jumpserver

文章目录 前言一、背景二、使用步骤1.基础环境准备2.拉取镜像3.进行部署4.备份记录启动命令 前言 记录一下使用docker形式部署jumpserver服务的 一、背景 搭建一个jumpserver的堡垒机&#xff0c;但是发现之前是二进制文件部署的&#xff0c;会在物理机上部署污染环境&#x…

(62)使用RLS自适应滤波器进行系统辨识的MATLAB仿真

文章目录 前言一、基本概念二、RLS算法原理三、RLS算法的典型应用场景四、MATLAB仿真代码五、仿真结果1.滤波器的输入信号、参考信号、输出信号、误差信号2.对未知系统进行辨识得到的系数 总结与后续 前言 RLS&#xff08;递归最小二乘&#xff09;自适应滤波器是一种用于系统…

算法每日双题精讲——滑动窗口(长度最小的子数组,无重复字符的最长子串)

&#x1f31f;快来参与讨论&#x1f4ac;&#xff0c;点赞&#x1f44d;、收藏⭐、分享&#x1f4e4;&#xff0c;共创活力社区。 &#x1f31f; 别再犹豫了&#xff01;快来订阅我们的算法每日双题精讲专栏&#xff0c;一起踏上算法学习的精彩之旅吧&#xff01;&#x1f4aa;…