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.
11月 18, 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
点一下关注吧!!!非常感谢!!持续更新!!! 大数据篇正在更新!https://blog.csdn.net/w776341482/category_12713819.html 目前已经更新到了: MyBatisÿ…...
kubernetes学习-使用metrics-server监控集群资源和查看日志
kubernetes学习-使用metrics-server监控集群资源和查看日志 一 、简介二、应用场景三、部署四、查看日志 一 、简介 Metrics Server 是一个用于 Kubernetes 集群的监控工具,它用于收集、存储和提供关于集群中各种资源的度量数据。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时,没有提供…...
CCNP_SEC_ASA 第三天作业
实验需求: ASA 使用列表放行 Outside 路由器到 DMZ 路由器的 WWW 流量并拒绝 Telnet 流量,当放行和拒绝流量匹配后产生日志通告。 提示:需要使能 ASA的日志功能和 DMZ路由器的 HTTP功能。 设备配置: ##此处展示各设备的配置&am…...
TypeError: Cannot read properties of null (reading ‘ce‘)
vue项目本地跑不起来,但是build之后能运行,本地报错 是因为你的vue版本不对,你的package可能是这样写的 这个表示你允许你的npm安装vue3的任意版本,但是build是按照这个版本来的,所以build之后能运行,本地运…...
AdminJS - 集成 MySQL 的现代化管理面板开发指南
AdminJS - 集成 MySQL 的现代化管理面板开发指南 MySQL 集成配置 首先需要安装必要的依赖: npm install adminjs adminjs/express express npm install adminjs/sequelize sequelize mysql2基础配置示例 const AdminJS require(adminjs) const AdminJSExpress …...
上传文件(vue3)
使用el-upload 先上传到文件服务器,生成url 然后点击确定按钮: 保存数据 <template><el-dialog top"48px" width"500" title"新增协议" :modelValue"visible" close"handleClose()">…...
【Win10 环境vscode配置boost】
文章目录 Boost exe版本windows环境安装vscode配置安装测试总结 Boost exe版本windows环境安装 这里不介绍boost源码安装,请自行网络搜索。本文要介绍的是window下单c文件(cpp),调用boost库的执行配置。不涉及多文件。 安装文件下…...
中间件 redis安装
redis官网地址: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,远程下载redis压缩包,或去官网下载:Downloads …...
[java] 简单的熔断器scala语言案例
failureRateInterval时间内如果addEx(错误)达到 maxFailuresPerInterval 次数,则fused方法返回true,表示触发熔断,进入冷却期coolingInterval,冷却期内fused方法返回true,冷却期过后进入下一个错误统计周期。 scala语言完成 imp…...
【java】序列化的种类和使用场景
文章目录 序列化概述什么是序列化?序列化的作用 Java内置序列化java.io.Serializable接口使用ObjectOutputStream和ObjectInputStream优缺点分析 自定义序列化实现Externalizable接口自定义序列化方法适用场景 第三方序列化框架KryoProtobuf (Google Protocol Buffe…...
Qt5与Qt6中的高DPI缩放属性解析
在Qt5中,高DPI缩放默认是禁用的。为了启用它,开发者需要设置Qt::AA_EnableHighDpiScaling应用程序属性。然而,在Qt6中,高DPI缩放默认是启用的,并且不能被禁用。这种变化使得开发者在处理高分辨率屏幕时更加方便&#x…...
Mac使用总结
Mac 常用快捷键 复制:Cmdc粘贴:Cmdv只粘贴文档: ShiftCmdv行首: Cmd<行尾:Cmd>鼠标处选中到行首:ShiftCmd<鼠标处选中到行尾:ShiftCmd>选中整行:上面两个命令组合鼠标处…...
【日期规则】EXCEl 自定义日期匹配规则,学习基础知识,自由匹配场景
excel 新建规则工具路径:开始 - 条件格式 - 新建规则 B$1TODAY() 注意:新建规则后,要点击 条件格式 - 管理规则 - 应用于 要选择规则应用范围 使用场景: excel 做进度管理当中可以查看当天的情况;每周的学习规划 或…...
苹果电脑可以安装windows操作系统吗?Mac OS X/OS X/macOS傻傻分不清?macOS系统的Java支持?什么是macOS的五大API法王?
苹果电脑可以安装windows操作系统吗? 先抛开虚拟机安装,苹果电脑可以安装Windows操作系统。苹果公司提供了一个名为Boot Camp的软件,它允许用户在Mac电脑上安装Windows操作系统。通过Boot Camp,用户可以在启动电脑时选择是要进入macOS还是Wi…...
芋道SpringBoot配置Maven、创建SpringBoot项目、创建Web接口、读取配置信息
🌹作者主页:青花锁 🌹简介:Java领域优质创作者🏆、Java微服务架构公号作者😄 🌹简历模板、学习资料、面试题库、技术互助 🌹文末获取联系方式 📝 系列文章目录 第一章 芋…...
物理机内网穿透
前言: 本文主要讲述如何使用内网穿透以及其安全性。 将带领大家在公网上搭建几个常用靶场。 一,什么是内网穿透。 大多数情况下,我们的个人电脑都处于内网,即没有可公开访问的独立 IP 地址,因此其他内网用户找不到…...
Vue 3: 通过图片链接获取图片颜色,间接设置背景颜色
在现代Web开发中,动态获取和处理图像数据是一个常见的需求。例如,你可能希望自动提取一张图片的主色调,以便根据这些颜色进行UI主题调整或其他视觉效果的处理。本文将介绍如何在Vue 3项目中,通过一个图片链接获取图片的颜色信息。…...
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:…...
如何使用生成式AI实现跨领域内容生成
文章目录 引言生成式AI的基本概念定义与分类技术发展现状 跨领域内容生成的技术实现数据准备模型选择与设计训练策略 应用案例分析教育培训新闻媒体文化创意产业 实践建议确定明确的目标构建合适的团队持续迭代改进遵守法律法规 结论 引言 在当今数字化时代,信息的…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...
2024年赣州旅游投资集团社会招聘笔试真
2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...
[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?
论文网址:pdf 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记,谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...
苍穹外卖--缓存菜品
1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...
Nginx server_name 配置说明
Nginx 是一个高性能的反向代理和负载均衡服务器,其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机(Virtual Host)。 1. 简介 Nginx 使用 server_name 指令来确定…...
《基于Apache Flink的流处理》笔记
思维导图 1-3 章 4-7章 8-11 章 参考资料 源码: https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...
iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈
在日常iOS开发过程中,性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期,开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发,但背后往往隐藏着系统资源调度不当…...
从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践
作者:吴岐诗,杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言:融合数据湖与数仓的创新之路 在数字金融时代,数据已成为金融机构的核心竞争力。杭银消费金…...
pycharm 设置环境出错
pycharm 设置环境出错 pycharm 新建项目,设置虚拟环境,出错 pycharm 出错 Cannot open Local Failed to start [powershell.exe, -NoExit, -ExecutionPolicy, Bypass, -File, C:\Program Files\JetBrains\PyCharm 2024.1.3\plugins\terminal\shell-int…...
