SpringBoot——分层解耦、IOC、依赖注入

三层架构 

如下图,创建Dao的接口以及该接口的实现类,Service也一样

  Dao

 // Dao接口
public interface UserDao {public List<String> findAll();
}// Dao接口的实现
public class UserDaoImpl implements UserDao {// 加载用户数据@Overridepublic List<String> findAll() {InputStream in = this.getClass().getClassLoader().getResourceAsStream("user.txt");ArrayList<String> lines = IoUtil.readLines(in, StandardCharsets.UTF_8, new ArrayList<>());return lines;}
}

 Service

// UserService 接口
public interface UserService {public List<User> findAll();
}// UserService 接口实现类
public class UserServiceImpl implements UserService {private UserDao userDao = new UserDaoImpl(); // usage@Overridepublic List<User> findAll() {
// 1. 调用dao,获取数据List<String> lines = userDao.findAll();// 2. 解析用户信息,转换为User对象 -> list集合List<User> userList = lines.stream().map(line -> {String[] parts = line.split( ",");Integer id = Integer.parseInt(parts[0]);String username = parts[1];String password = parts[2];String name = parts[3];Integer age = Integer.parseInt(parts[4]);LocalDateTime updateTime = LocalDateTime.parse(parts[5], DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));return new User(id, username, password, name, age, updateTime);}).toList();return userList;}
}

 Controller

import java.util.List;@RestController
public class UserController {private UserService userService = new UserServiceImpl(); // 1 usage@GetMapping("/book")public List<User> list(){// 1. 调用service,获取数据List<User> userList = userService.findAll();// 2. 返回数据(json)return userList;}
}

分层解耦

实现分层解耦的思路是什么?

控制反转: Inversion Of Control,简称IOC。对象的创建控制权由程序自身转移到外部(容器),这种思想称为控制反转。

依赖注入: Dependency Injection,简称DI。容器为应用程序提供运行时,所依赖的资源,称之为依赖注入。

Bean对象: IOC容器中创建、管理的对象,称之为Bean。

  • 将项目中的类交给IOC容器管理(IOC,控制反转)

  • 应用程序运行时需要什么对象,直接依赖容器为其提供(DI,依赖注入)

 IOC容器管理对象

注解说明位置
@Component声明bean的基础注解不属于以下三类时,用此注解
@Controller@Component的衍生注解(内部封装了@Component标注在控制层类上
@Service@Component的衍生注解(内部封装了@Component标注在业务层类上
@Repository@Component的衍生注解(内部封装了@Component标注在数据访问层类上(由于与mybatis整合,用的少)

@Repository("UserDao") // 定义Bean名称,但通常不会定义

 

依赖注入

属性注入(适用于快速开发)

@RestController  
public class UserController {  @Autowired  private UserService userService;  //......  
}
  • 优点:代码简洁,方便快速开发。
  • 缺点:隐藏了类之间的依赖关系,可能会破坏类的封装性。

构造函数注入(对规范性要求高)

@RestController  
public class UserController {  private final UserService userService;  @Autowired  public UserController(UserService userService) {  this.userService = userService;  }  
}
  • 优点:能够清晰地看到类的依赖关系,提高了代码的安全性。
  • 缺点:代码繁琐,如果构造参数过多,可能会导致构造函数臃肿。
  • 注意:如果只有一个构造函数,@Autowired注解可以省略。

setter注入

@RestController  
public class UserController {  private UserService userService;  @Autowired  public void setUserService(UserService userService) {  this.userService = userService;  }  
}
  • 优点:保持了类的封装性,依赖关系更清晰。
  • 缺点:需要额外编写setter方法,增加了代码量。

多个类型相同的Bean注入

  • @Autowired注解,默认是按照类型进行注入的。
  • 如果存在多个相同类型的bean,将会报出如下错误:
    Field userService in com.itheima.controller.UserController required a single bean, but 2 were found:
    - userServiceImpl1: defined in file [D:\idea_workspace_web_ai\web-project1\springboot-web-quickstart\target\classes\com\itheima\service\impl\UserServiceImpl.class]
    - userServiceImpl2: defined in file [D:\idea_workspace_web_ai\web-project1\springboot-web-quickstart\target\classes\com\itheima\service\impl\UserServiceImpl2.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

    以下为一些解决方法

  • 方案一:@Primary(@Primary 注解,你可以清晰地定义在存在多个候选 Bean 时,哪一个应该是默认的注入对象,从而避免潜在的冲突和不确定性):就是说在使用@Autowired时注入的是标了@Primary的Bean码
    @Primary
    @Service
    public class UserServiceImpl implements UserService {@Overridepublic List<User> list(){//省略......}
    }
  • 方案二:@Qualifier

    @RestController
    public class UserController {@Autowired@Qualifier("userServiceImpl1")private UserService userService;
    }
  • 方案三:@Resource

    @RestController
    public class UserController {@Resource(name = "userServiceImpl1")private UserService userService;
    }

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

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

相关文章

【数据结构——栈和队列】括号配对(头歌实践教学平台习题)【合集】

目录&#x1f60b; 任务描述 相关知识 测试说明 我的通关代码: 测试结果&#xff1a; 任务描述 本关任务&#xff1a;编写一个程序利用栈判断左、右圆括号是否配对。 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a;栈对括号的处理。 栈对括号的处理 &…

企业级日志分析系统ELK之ELK概述

ELK 概述 ELK 介绍 什么是 ELK 早期IT架构中的系统和应用的日志分散在不同的主机和文件&#xff0c;如果应用出现问题&#xff0c;开发和运维人员想排 查原因&#xff0c;就要先找到相应的主机上的日志文件再进行查找和分析&#xff0c;所以非常不方便&#xff0c;而且还涉及…

js后端开发之Next.js、Nuxt.js 与 Express.js

后端js之Next.js、Nuxt.js 与 Express.js 在现代 Web 开发中&#xff0c;JavaScript 已经成为前后端通用的编程语言&#xff0c;而选择合适的后端框架则是构建高效、可扩展应用程序的关键。本文将带你深入了解三个流行的 JavaScript 后端框架&#xff1a;Next.js、Nuxt.js 和 …

CSS的2D和3D动画效果

CSS的2D和3D动画效果&#xff1a;网页动态设计的魔法 在现代网页设计中&#xff0c;动画已经成为提升用户体验的重要元素。通过引入动态效果&#xff0c;我们不仅可以使交互更加流畅和直观&#xff0c;还能吸引用户的注意力&#xff0c;增强品牌认知度。CSS提供了强大的工具&a…

离开wordpress

wordpress确实挺好用的 插件丰富 主题众多 收费的插件也很多 国内的做主题的也挺好 但是服务器跑起来各种麻烦伤脑筋 需要花在维护的时间太多了 如果你的网站持续盈利 你就会更担心访问质量访问速度 而乱七八糟的爬虫黑客 让你的服务器不堪重负 突然有一天看到了静态站…

pyqt+ubuntu18.04+designer+测试是否安装成功

引用&#xff1a; Ubuntu Linux安装PyQt5并配置Qt Designer 在Visual Studio Code中使用PyQt5开发python GUI应用程序 Linux环境下在Vscode中安装和设置PyQt5插件 其中&#xff0c; 测试是否安装成功 1、设置好之后在vscode编辑器的左侧文件目录栏空白位置右键&#xff0…

系统启动优化首笔交易慢优化

系统启动优化 1. 启动耗时原因&#xff1a; bean加载文件&#xff0c;资源&#xff0c;配置扫描加载其它&#xff08;网络通讯&#xff0c;GC等&#xff09; 2. 优化手段 扫描路径尽可能精确关闭swagger扫描bean加载使用懒加载&#xff08;Lazy&#xff09;升级jdk&#xff0…

Apache Doris 3.0.3 版本正式发布

亲爱的社区小伙伴们&#xff0c;Apache Doris 3.0.3 版本已于 2024 年 12 月 02 日正式发布。 该版本进一步提升了系统的性能及稳定性&#xff0c;欢迎大家下载体验。 GitHub 下载&#xff1a;https://github.com/apache/doris/releases 官网下载&#xff1a;Apache Doris - D…

torchaudio.load 段错误

使用 torchaudio.load 时出现崩溃&#xff0c;如图 解决&#xff1a; 安装 ffmpeg ​conda install ffmpeg -c conda-forge 尝试但没解决问题的方法包括 重装 cuda&#xff0c;重装 pytorch&#xff0c;安装 PySoundFile、SoundFile、sox。

介绍一下CSS中伪类和伪元素的概念

一、伪类&#xff08;Pseudo - Classes&#xff09; 1. 定义 伪类是添加到选择器的关键字&#xff0c;用于定义元素的特殊状态。这些状态不是由文档树中的结构或属性来表示&#xff0c;而是基于用户行为&#xff08;如鼠标悬停&#xff09;、元素状态&#xff08;如被选中&am…

React 第十六节 useCallback 使用详解注意事项

useCallback 概述 1、useCallback 是在React 中多次渲染缓存函数的 Hook&#xff0c;返回一个函数的 memoized的值&#xff1b; 2、如果多次传入的依赖项不变&#xff0c;那么多次定义的时候&#xff0c;返回的值是相同的,防止频繁触发更新&#xff1b; 3、多应用在 父组件为函…

Chrome webdriver下载-避坑

WebDriver以原生的方式驱动浏览器&#xff0c;不需要调整环境变量。 一、window版 1.chrome和chromedriver下载地址&#xff1a; Chrome for Testing availability 我下载的是如下两个安装包&#xff0c;解压即可。 2.导包 pip install selenium然后用python代码引用即可…

PyQt事件机制练习

一、思维导图 二、代码 import sysfrom PyQt6.QtTextToSpeech import QTextToSpeech from PyQt6.QtWidgets import QApplication, QWidget, QLabel, QPushButton, QLineEdit from PyQt6 import uic from PyQt6.QtCore import Qt, QTimerEvent, QTimeclass MyWidget(QWidget):d…

【Rive】Android与Rive交互

1 Android与Rive交互的常用接口 1.1 RiveAnimationView参数 <app.rive.runtime.kotlin.RiveAnimationViewandroid:id"id/rive_view"android:layout_width"match_parent"android:layout_height"match_parent"android:adjustViewBounds"…

Maven、mybatis框架

一、Maven介绍 1.概念&#xff1a; Maven项目对象模型(POM)&#xff0c;可以通过一小段描述信息来管理项目的构建&#xff0c;报告和文档的项目管理工具软件。 2.为啥使用maven: 之前项目中需要引入大量的jar包。这些jar从网上下载&#xff0c;可能下载地址不同意。这些jar之间…

使用 Python 爬取某网站简历模板(bs4/lxml+协程)

使用 Python 爬取站长素材简历模板 简介 在本教程中&#xff0c;我们将学习如何使用 Python 来爬取站长素材网站上的简历模板。我们将使用requests和BeautifulSoup库来发送 HTTP 请求和解析 HTML 页面。本教程将分为两个部分&#xff1a;第一部分是使用BeautifulSoup的方法&am…

什么是厄尔米特(Hermitian)矩阵?

厄米矩阵&#xff08;Hermitian Matrix&#xff09;定义 在数学和物理中&#xff0c;厄米矩阵是满足以下条件的复方阵&#xff1a; A A † \mathbf{A}\mathbf{A}^\dagger AA† 其中&#xff0c; A † \mathbf{A}^\dagger A†表示矩阵 A \mathbf{A} A的共轭转置&#xff0c;即…

HCIA-Access V2.5_2_2网络通信基础_TCP/IP协议栈报文封装

TCP/IP协议栈的封装过程 用户从应用层发出数据先会交给传输层&#xff0c;传输层会添加TCP或者UDP头部&#xff0c;然后交给网络层&#xff0c;网络层会添加IP头部&#xff0c;然后交给数据链路层&#xff0c;数据链路层会添加以太网头部和以太网尾部&#xff0c;最后变成01这样…

爬虫获取的数据能否用于商业分析?

根据搜索结果&#xff0c;爬虫获取的数据能否用于商业分析&#xff0c;主要取决于以下几个因素&#xff1a; 数据的合法性与合规性&#xff1a; 爬虫技术本身并不违法&#xff0c;关键在于使用的方式和目的。爬虫技术的使用必须遵守相关法律法规&#xff0c;如《反不正当竞争法…

数据湖治理最佳实践

如果没有最佳实践&#xff0c;存储可能会变得无法维护。自动化数据质量、生命周期和隐私功能可持续清理/移动数据湖中的数据。数据湖正成为企业从大数据中提取价值的一种日益可行的解决方案&#xff0c;对于早期采用者和新用户来说都是合理的下一步。在独立的逻辑区域中随时可用…