当前位置: 首页 > news >正文

Java-27 深入浅出 Spring - 实现简易Ioc-03 在上节的业务下手动实现IoC

点一下关注吧!!!非常感谢!!持续更新!!!

大数据篇正在更新!https://blog.csdn.net/w776341482/category_12713819.html

在这里插入图片描述

目前已经更新到了:

  • MyBatis(已更完)
  • Spring(正在更新…)

在这里插入图片描述

上节进度

上节完成了基本代码的编写,本节我们继续。本节将进行 IoC的实现。

IoC 实现

此时我们需要一个 Bean 的管理容器,当我们需要 new 对象的时候,可以直接从容器中获取出来。但是我们需要在程序启动的时候(当然也可以懒加载)就把这些对象初始化出来,所以我们需要 XML 来告诉容器需要加载什么内容。

IoC(Inversion of Control,控制反转)简介

控制反转(IoC)是一种设计原则,用于实现组件间的解耦,是面向对象编程中非常重要的概念之一。IoC的核心思想是将程序中对对象的控制权从调用方转移到框架或容器中,使得对象之间的依赖关系由容器来管理。

IoC 的特点

解耦

IoC通过将依赖的管理和创建责任交给容器,减少了模块之间的耦合性,增强了系统的可维护性和可扩展性。

动态依赖管理

容器根据配置或注解动态地将依赖注入到对象中,而不需要硬编码的依赖关系。

灵活性

对象的依赖可以在运行时动态修改,只需更改配置即可,不需要修改代码。

IoC 的应用场景

IoC被广泛应用于各种软件开发框架和项目中,以下是几个典型应用:

  • Spring Framework:Spring框架使用IoC容器管理Bean的生命周期和依赖关系。开发者只需定义组件及其依赖,具体的实例化和依赖注入由Spring容器完成。
  • Guice 和 Dagger:这些轻量级DI框架在Java项目中也很流行,提供了简单高效的依赖注入功能。
  • 前端框架(如Angular):Angular中也实现了IoC,通过其依赖注入系统来管理组件和服务之间的依赖关系。

IoC 的优势

  • 增强模块化:通过减少模块之间的直接依赖,促进模块化设计。
  • 提高测试性:依赖注入可以方便地替换依赖对象,从而支持单元测试。
  • 增强灵活性:通过配置或注解动态注入依赖,无需修改代码即可适应变化。
  • 便于维护:解耦使得系统在增加或修改功能时影响最小。

IoC 的限制

  • 学习曲线:初学者需要一定时间理解IoC和DI的概念。
  • 运行时性能开销:IoC容器在运行时解析依赖关系可能会引入一些性能开销。
  • 复杂性:在大型项目中,过度使用IoC可能导致配置和依赖关系变得复杂。

Resources

Resources 目录下

beans.xml

我们先编写一个 XML 来保存我们的 Bean 的信息:

<?xml version="1.0" encoding="UTF-8" ?>
<!-- BeanFactory 类会进行处理这块内容 -->
<beans><!-- WzkConnectionUtils 交给容器管理 --><bean id="wzkConnectionUtils" class="wzk.utils.WzkConnectionUtils"></bean><!-- 依赖了工具类 WzkConnectionUtils --><!-- id 是放入到容器中的名称 --><bean id="wzkAccountDao" class="wzk.dao.impl.JdbcWzkAccountDaoImpl"><!-- name是成员变量名字 ref是引用从容器中拿对象 --><property name="WzkConnectionUtils" ref="wzkConnectionUtils"/></bean><!-- 依赖了 WzkAccountDao --><bean id="wzkTransferService" class="wzk.service.impl.WzkTransferServiceImpl"><!-- name是成员变量名字 ref是引用从容器中拿对象 --><property name="WzkAccountDao" ref="wzkAccountDao"></property></bean>
</beans>

对应的内容截图如下所示:
在这里插入图片描述
注意:需要将 beans.xml 放置到 resources 目录下。
在这里插入图片描述

Proxy

BeanFactory

public class BeanFactory {private BeanFactory() {}/*** 全局容器 对象都存储到这里*/private static Map<String, Object> map = new HashMap<>();static {// 对 XML 进行处理,这里可以参考我们之前 手写的MyBatis的部分// 静态代码块 来进行初始化InputStream resourceAsSteam = BeanFactory.class.getClassLoader().getResourceAsStream("beans.xml");SAXReader saxReader = new SAXReader();try {Document document = saxReader.read(resourceAsSteam);Element rootElement = document.getRootElement();List<Element> beanList = rootElement.selectNodes("//bean");for (Element element : beanList) {// 处理每个 Bean 元素String id = element.attributeValue("id");String clazz = element.attributeValue("class");// 反射拿到对象Class<?> aClass = Class.forName(clazz);Object object = aClass.newInstance();// 保存到容器中map.put(id, object);}List<Element> propertyList = rootElement.selectNodes("//property");for (Element element : propertyList) {// 处理每个依赖关系String name = element.attributeValue("name");String ref = element.attributeValue("ref");// 拿到父级节点 它下边的 property都是它的依赖Element parentElement = element.getParent();String parentId = parentElement.attributeValue("id");// 通过父级的 ID 拿到对象Object parentObject = map.get(parentId);// 拿到父级的所有方法 Get Set 等等Method[] methods = parentObject.getClass().getMethods();for (Method method : methods) {// 如果是 set 方法的话 我们调用就可以将它的依赖赋值给父级if (method.getName().equalsIgnoreCase("set" + name)) {method.invoke(parentObject, map.get(ref));}}// 记得更新容器的内容map.put(parentId, parentObject);}System.out.println("BeanFactory 初始化完毕 map:" + map);} catch (Exception e) {System.out.println("BeanFactory 初始化失败");e.printStackTrace();}}public static Object getBean(String id) {return map.get(id);}}

对应的截图如下所示:

在这里插入图片描述

Controller

WzkServlet

我们对 WzkServlet 进行一些修改:

@WebServlet(name="wzkServlet", urlPatterns = "/wzkServlet")
public class WzkServlet extends HttpServlet {// ========================== 2 ==========================// 由 BeanFactory 处理private WzkTransferService wzkTransferService = (WzkTransferService) BeanFactory.getBean("wzkTransferService");// =======================================================@Overrideprotected void doGet(javax.servlet.http.HttpServletRequest req, javax.servlet.http.HttpServletResponse resp) throws javax.servlet.ServletException, IOException {System.out.println("=== WzkServlet doGet ===");// ======================= 1 =============================// 由于没有 Spring 的帮助 我们就需要手动去创建和维护依赖之间的关系// 组装 DAO DAO层依赖于 ConnectionUtils 和 DruidUtils// JdbcWzkAccountDaoImpl jdbcWzkAccountDaoImpl = new JdbcWzkAccountDaoImpl();// jdbcWzkAccountDaoImpl.setConnectionUtils(new WzkConnectionUtils());// 组装 Service// WzkTransferServiceImpl wzkTransferService = new WzkTransferServiceImpl();// wzkTransferService.setWzkAccountDao(jdbcWzkAccountDaoImpl);// ======================================================// 执行业务逻辑try {wzkTransferService.transfer("1", "2", 100);} catch (Exception e) {e.printStackTrace();System.out.println("=== transfer error ====");}resp.setContentType("application/json;charset=utf-8");resp.getWriter().print("=== WzkServlet doGet ===");}}

WzkServlet(2)

还有一种写法也是类似的,这样的处理方式也可以顺利执行的。

// ========================== 3 ==========================// 另一种方式 相同的private WzkTransferService wzkTransferService;@Overridepublic void init() throws ServletException {super.init();this.wzkTransferService = (WzkTransferService) BeanFactory.getBean("wzkTransferService");}// ======================================================

测试运行

我们运行代码之后,可以看到控制台如下所示:

BeanFactory 初始化完毕 map:{wzkTransferService=wzk.service.impl.WzkTransferServiceImpl@5dfdd67c, wzkAccountDao=wzk.dao.impl.JdbcWzkAccountDaoImpl@380d9fc0, wzkConnectionUtils=wzk.utils.WzkConnectionUtils@2d150354}
=== WzkServlet doGet ===
Loading class `com.mysql.jdbc.Driver'. This is deprecated. The new driver class is `com.mysql.cj.jdbc.Driver'. The driver is automatically registered via the SPI and manual loading of the driver class is generally unnecessary.
1118, 2024 6:24:24 下午 com.alibaba.druid.pool.DruidDataSource info
信息: {dataSource-1} inited
transfer fromResult: 1 toResult: 1

对应的控制台结束如下所示:
在这里插入图片描述

查看结果

数据库的结果已经变化了,可以看到结果如下:
在这里插入图片描述
当然,刚才的代码打印的内容,也说明我们的代码是正常工作的。
(你可以打断点进行调试)

目前问题

我们虽然已经实现了简易的 IoC,但是对于当前业务来说,我们还需要对事务进行控制,此时需要我们实现一个事务的管理器,将采取和数据库一样,用 ThreadLocal 来进行控制。

相关文章:

Java-27 深入浅出 Spring - 实现简易Ioc-03 在上节的业务下手动实现IoC

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; 大数据篇正在更新&#xff01;https://blog.csdn.net/w776341482/category_12713819.html 目前已经更新到了&#xff1a; MyBatis&#xff…...

kubernetes学习-使用metrics-server监控集群资源和查看日志

kubernetes学习-使用metrics-server监控集群资源和查看日志 一 、简介二、应用场景三、部署四、查看日志 一 、简介 Metrics Server 是一个用于 Kubernetes 集群的监控工具&#xff0c;它用于收集、存储和提供关于集群中各种资源的度量数据。Metrics Server 是 Kubernetes 中一…...

解决 Git Permission denied 问题

前言 push项目时出现gitgithub.com: Permission denied (publickey). fatal: Could not read from remote repository.Please make sure you have the correct access rights and the repository exists.出现这个问题表示你在尝试将本地代码推送到GitHub时&#xff0c;没有提供…...

CCNP_SEC_ASA 第三天作业

实验需求&#xff1a; ASA 使用列表放行 Outside 路由器到 DMZ 路由器的 WWW 流量并拒绝 Telnet 流量&#xff0c;当放行和拒绝流量匹配后产生日志通告。 提示&#xff1a;需要使能 ASA的日志功能和 DMZ路由器的 HTTP功能。 设备配置&#xff1a; ##此处展示各设备的配置&am…...

TypeError: Cannot read properties of null (reading ‘ce‘)

vue项目本地跑不起来&#xff0c;但是build之后能运行&#xff0c;本地报错 是因为你的vue版本不对&#xff0c;你的package可能是这样写的 这个表示你允许你的npm安装vue3的任意版本&#xff0c;但是build是按照这个版本来的&#xff0c;所以build之后能运行&#xff0c;本地运…...

AdminJS - 集成 MySQL 的现代化管理面板开发指南

AdminJS - 集成 MySQL 的现代化管理面板开发指南 MySQL 集成配置 首先需要安装必要的依赖&#xff1a; npm install adminjs adminjs/express express npm install adminjs/sequelize sequelize mysql2基础配置示例 const AdminJS require(adminjs) const AdminJSExpress …...

上传文件(vue3)

使用el-upload 先上传到文件服务器&#xff0c;生成url 然后点击确定按钮&#xff1a; 保存数据 <template><el-dialog top"48px" width"500" title"新增协议" :modelValue"visible" close"handleClose()">…...

【Win10 环境vscode配置boost】

文章目录 Boost exe版本windows环境安装vscode配置安装测试总结 Boost exe版本windows环境安装 这里不介绍boost源码安装&#xff0c;请自行网络搜索。本文要介绍的是window下单c文件&#xff08;cpp&#xff09;&#xff0c;调用boost库的执行配置。不涉及多文件。 安装文件下…...

中间件 redis安装

redis官网地址&#xff1a;Redis - The Real-time Data Platform 环境 CentOS Linux release 7.9.2009 (Core) java version "17.0.12" 2024-07-16 LTS 1、通过压缩包安装redis 1&#xff0c;远程下载redis压缩包&#xff0c;或去官网下载&#xff1a;Downloads …...

[java] 简单的熔断器scala语言案例

failureRateInterval时间内如果addEx(错误)达到 maxFailuresPerInterval 次数&#xff0c;则fused方法返回true,表示触发熔断&#xff0c;进入冷却期coolingInterval&#xff0c;冷却期内fused方法返回true&#xff0c;冷却期过后进入下一个错误统计周期。 scala语言完成 imp…...

【java】序列化的种类和使用场景

文章目录 序列化概述什么是序列化&#xff1f;序列化的作用 Java内置序列化java.io.Serializable接口使用ObjectOutputStream和ObjectInputStream优缺点分析 自定义序列化实现Externalizable接口自定义序列化方法适用场景 第三方序列化框架KryoProtobuf (Google Protocol Buffe…...

Qt5与Qt6中的高DPI缩放属性解析

在Qt5中&#xff0c;高DPI缩放默认是禁用的。为了启用它&#xff0c;开发者需要设置Qt::AA_EnableHighDpiScaling应用程序属性。然而&#xff0c;在Qt6中&#xff0c;高DPI缩放默认是启用的&#xff0c;并且不能被禁用。这种变化使得开发者在处理高分辨率屏幕时更加方便&#x…...

Mac使用总结

Mac 常用快捷键 复制&#xff1a;Cmdc粘贴&#xff1a;Cmdv只粘贴文档&#xff1a; ShiftCmdv行首&#xff1a; Cmd<行尾&#xff1a;Cmd>鼠标处选中到行首&#xff1a;ShiftCmd<鼠标处选中到行尾&#xff1a;ShiftCmd>选中整行&#xff1a;上面两个命令组合鼠标处…...

【日期规则】EXCEl 自定义日期匹配规则,学习基础知识,自由匹配场景

excel 新建规则工具路径&#xff1a;开始 - 条件格式 - 新建规则 B$1TODAY() 注意&#xff1a;新建规则后&#xff0c;要点击 条件格式 - 管理规则 - 应用于 要选择规则应用范围 使用场景&#xff1a; excel 做进度管理当中可以查看当天的情况&#xff1b;每周的学习规划 或…...

苹果电脑可以安装windows操作系统吗?Mac OS X/OS X/macOS傻傻分不清?macOS系统的Java支持?什么是macOS的五大API法王?

苹果电脑可以安装windows操作系统吗? 先抛开虚拟机安装&#xff0c;苹果电脑可以安装Windows操作系统。苹果公司提供了一个名为Boot Camp的软件&#xff0c;它允许用户在Mac电脑上安装Windows操作系统。通过Boot Camp&#xff0c;用户可以在启动电脑时选择是要进入macOS还是Wi…...

芋道SpringBoot配置Maven、创建SpringBoot项目、创建Web接口、读取配置信息

&#x1f339;作者主页&#xff1a;青花锁 &#x1f339;简介&#xff1a;Java领域优质创作者&#x1f3c6;、Java微服务架构公号作者&#x1f604; &#x1f339;简历模板、学习资料、面试题库、技术互助 &#x1f339;文末获取联系方式 &#x1f4dd; 系列文章目录 第一章 芋…...

物理机内网穿透

前言&#xff1a; 本文主要讲述如何使用内网穿透以及其安全性。 将带领大家在公网上搭建几个常用靶场。 一&#xff0c;什么是内网穿透。 大多数情况下&#xff0c;我们的个人电脑都处于内网&#xff0c;即没有可公开访问的独立 IP 地址&#xff0c;因此其他内网用户找不到…...

Vue 3: 通过图片链接获取图片颜色,间接设置背景颜色

在现代Web开发中&#xff0c;动态获取和处理图像数据是一个常见的需求。例如&#xff0c;你可能希望自动提取一张图片的主色调&#xff0c;以便根据这些颜色进行UI主题调整或其他视觉效果的处理。本文将介绍如何在Vue 3项目中&#xff0c;通过一个图片链接获取图片的颜色信息。…...

opencv-python的简单练习

题目1.读取一张彩色图像并将其转换为灰度图。 import cv2 # 读取图片文件 img cv2.imread(./1.png)# 将原图灰度化 img_gray cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)# 输出图片 cv2.imshow(img,img) cv2.imshow(img_g,img_gray) # 进行阻塞 cv2.waitKey(0) 题目2&#xff1a;…...

如何使用生成式AI实现跨领域内容生成

文章目录 引言生成式AI的基本概念定义与分类技术发展现状 跨领域内容生成的技术实现数据准备模型选择与设计训练策略 应用案例分析教育培训新闻媒体文化创意产业 实践建议确定明确的目标构建合适的团队持续迭代改进遵守法律法规 结论 引言 在当今数字化时代&#xff0c;信息的…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别

一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...

反向工程与模型迁移:打造未来商品详情API的可持续创新体系

在电商行业蓬勃发展的当下&#xff0c;商品详情API作为连接电商平台与开发者、商家及用户的关键纽带&#xff0c;其重要性日益凸显。传统商品详情API主要聚焦于商品基本信息&#xff08;如名称、价格、库存等&#xff09;的获取与展示&#xff0c;已难以满足市场对个性化、智能…...

Xshell远程连接Kali(默认 | 私钥)Note版

前言:xshell远程连接&#xff0c;私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

VTK如何让部分单位不可见

最近遇到一个需求&#xff0c;需要让一个vtkDataSet中的部分单元不可见&#xff0c;查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行&#xff0c;是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示&#xff0c;主要是最后一个参数&#xff0c;透明度…...

pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)

目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关&#xff0…...

均衡后的SNRSINR

本文主要摘自参考文献中的前两篇&#xff0c;相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程&#xff0c;其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt​ 根发送天线&#xff0c; n r n_r nr​ 根接收天线的 MIMO 系…...

QT3D学习笔记——圆台、圆锥

类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体&#xff08;对象或容器&#xff09;QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质&#xff08;定义颜色、反光等&#xff09;QFirstPersonC…...

R 语言科研绘图第 55 期 --- 网络图-聚类

在发表科研论文的过程中&#xff0c;科研绘图是必不可少的&#xff0c;一张好看的图形会是文章很大的加分项。 为了便于使用&#xff0c;本系列文章介绍的所有绘图都已收录到了 sciRplot 项目中&#xff0c;获取方式&#xff1a; R 语言科研绘图模板 --- sciRplothttps://mp.…...

Rust 开发环境搭建

环境搭建 1、开发工具RustRover 或者vs code 2、Cygwin64 安装 https://cygwin.com/install.html 在工具终端执行&#xff1a; rustup toolchain install stable-x86_64-pc-windows-gnu rustup default stable-x86_64-pc-windows-gnu ​ 2、Hello World fn main() { println…...

xmind转换为markdown

文章目录 解锁思维导图新姿势&#xff1a;将XMind转为结构化Markdown 一、认识Xmind结构二、核心转换流程详解1.解压XMind文件&#xff08;ZIP处理&#xff09;2.解析JSON数据结构3&#xff1a;递归转换树形结构4&#xff1a;Markdown层级生成逻辑 三、完整代码 解锁思维导图新…...