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

Spring常见问题一:IOC和DI

IOC和DI

IOC和DI之间到底是什么关系? 什么是依赖关系?依赖关系会带来什么问题?Spring是怎么来支持依赖注入的?

引言

在现代软件开发中,面向对象编程(OOP)已经成为主流编程范式。然而,随着系统复杂性的增加,传统的OOP也暴露出一些不足。为了更好地管理代码的依赖关系和提高代码的可维护性,依赖注入(Dependency Injection,DI)和控制反转(Inversion of Control,IoC)等设计原则应运而生。本文将深入探讨IoC和DI之间的关系、依赖关系的定义及其问题,以及Spring框架如何支持依赖注入。

一、什么是控制反转(IoC)

控制反转(Inversion of Control,IoC)是一种设计原则,它将对象的创建和依赖关系的管理从代码中剥离出来,交由容器或框架处理。简单来说,IoC的核心思想是将控制权从应用程序代码转移到容器中,使应用程序更加灵活和易于维护。

1.1 IoC的实现方式

IoC有多种实现方式,最常见的包括:

  1. 依赖注入(Dependency Injection,DI):通过构造函数注入、Setter方法注入或接口注入的方式,将依赖对象传递给需要它们的对象。
  2. 服务定位器(Service Locator):通过一个集中管理的服务提供者,动态地获取依赖对象。

本文主要关注依赖注入这一实现方式。

1.2 IoC的优势

IoC的主要优势包括:

  • 解耦合:通过IoC,组件之间的依赖关系被外部容器管理,减少了代码中的耦合。
  • 可测试性:由于依赖对象可以被注入,单元测试时可以轻松地替换实际依赖为模拟对象。
  • 可维护性:通过配置文件或注解来管理依赖关系,代码的维护和修改变得更加简单。

二、什么是依赖注入(DI)

依赖注入(Dependency Injection,DI)是控制反转的一种实现方式,它通过外部化依赖关系,将对象的创建和管理交给容器来处理。DI使得对象不需要自己创建依赖对象,而是通过注入的方式获得它们。

2.1 DI的类型

依赖注入主要有三种类型:

  1. 构造函数注入:通过构造函数将依赖对象注入到目标对象中。

    public class Service {private Repository repository;public Service(Repository repository) {this.repository = repository;}
    }
    
  2. Setter方法注入:通过Setter方法将依赖对象注入到目标对象中。

    public class Service {private Repository repository;public void setRepository(Repository repository) {this.repository = repository;}
    }
    
  3. 接口注入:通过接口方法将依赖对象注入到目标对象中(这种方式较少使用)。

    public interface Service {void setRepository(Repository repository);
    }
    

2.2 DI的优势

DI的主要优势包括:

  • 增强模块化:通过DI,各个模块可以独立开发、测试和部署,降低了模块间的耦合。
  • 提高代码可读性:依赖关系通过注入方式显式声明,代码的依赖关系更加清晰。
  • 便于单元测试:通过注入模拟对象,单元测试变得更加简单和可靠。

三、什么是依赖关系

依赖关系是指一个对象依赖于另一个对象以完成其功能。在软件开发中,依赖关系是不可避免的,但如果处理不当,会导致代码的耦合性增加,难以维护和扩展。

3.1 依赖关系的定义

在面向对象编程中,依赖关系通常表现为一个类使用另一个类的实例。这种关系可以通过以下几种方式实现:

  1. 通过构造函数:在对象的构造函数中传递依赖对象。
  2. 通过方法参数:在方法调用时传递依赖对象。
  3. 通过成员变量:在类的成员变量中直接引用依赖对象。

3.2 依赖关系的分类

依赖关系可以分为强依赖和弱依赖:

  1. 强依赖:目标对象的存在完全依赖于依赖对象,缺少依赖对象,目标对象无法工作。
  2. 弱依赖:目标对象的某些功能依赖于依赖对象,但即使缺少依赖对象,目标对象仍能部分工作。

四、依赖关系带来的问题

不正确地处理依赖关系,会导致一系列问题,包括:

4.1 高耦合

高耦合是指系统中的模块或类之间的依赖关系过于紧密,以至于修改一个模块或类会影响到其他模块或类。高耦合会导致以下问题:

  • 代码难以维护:一处修改可能会引发连锁反应,需要修改多个地方。
  • 代码难以扩展:添加新功能时,需要修改大量现有代码,增加了出错的风险。
  • 单元测试困难:由于模块间依赖紧密,难以独立测试单个模块。

4.2 代码重用性低

高耦合会导致代码的重用性低,因为一个模块或类很难在不修改其他部分的情况下单独使用。

4.3 违反开闭原则

开闭原则(Open/Closed Principle)是指软件实体应该对扩展开放,对修改关闭。高耦合的代码往往需要频繁修改,从而违反了开闭原则。

五、Spring如何支持依赖注入

Spring框架是Java企业级开发中最流行的框架之一,它通过IoC容器来支持依赖注入。Spring的IoC容器负责管理对象的生命周期和依赖关系,从而实现低耦合和高可维护性的目标。

5.1 Spring IoC容器

Spring IoC容器是Spring框架的核心组件之一,它负责实例化、配置和组装对象。Spring IoC容器使用Java的反射机制和配置元数据(XML、Java注解或Java配置类)来管理依赖关系。

5.2 Spring中的依赖注入方式

Spring支持多种依赖注入方式,包括:

  1. 构造函数注入

    @Component
    public class Service {private final Repository repository;@Autowiredpublic Service(Repository repository) {this.repository = repository;}
    }
    
  2. Setter方法注入

    @Component
    public class Service {private Repository repository;@Autowiredpublic void setRepository(Repository repository) {this.repository = repository;}
    }
    
  3. 字段注入

    @Component
    public class Service {@Autowiredprivate Repository repository;
    }
    

5.3 配置方式

Spring支持多种配置方式来实现依赖注入,包括:

  1. 基于XML的配置

    <bean id="repository" class="com.example.Repository" />
    <bean id="service" class="com.example.Service"><constructor-arg ref="repository" />
    </bean>
    
  2. 基于注解的配置

    @Configuration
    public class AppConfig {@Beanpublic Repository repository() {return new Repository();}@Beanpublic Service service() {return new Service(repository());}
    }
    
  3. 基于Java配置类

    @Configuration
    @ComponentScan(basePackages = "com.example")
    public class AppConfig {
    }
    

5.4 Spring中的依赖解析

Spring使用依赖解析策略来确定如何满足依赖关系。主要有以下几种策略:

  1. 按类型自动装配(byType):根据依赖对象的类型自动装配。
  2. 按名称自动装配(byName):根据依赖对象的名称自动装配。
  3. 构造函数自动装配(constructor):通过构造函数自动装配依赖对象。

5.5 Spring中的作用域

Spring中的bean可以有不同的作用域,常见的作用域包括:

  1. 单例(Singleton):每个Spring IoC容器中只有一个bean实例(默认作用域)。
  2. 原型(Prototype):每次请求都会创建一个新的bean实例。
  3. 请求(Request):每个HTTP请求都会创建一个bean实例(用于Web应用程序)。
  4. 会话(Session):每个HTTP会

话都会创建一个bean实例(用于Web应用程序)。

5.6 Spring中的依赖生命周期管理

Spring IoC容器不仅负责依赖注入,还负责管理bean的生命周期。Spring提供了多个生命周期回调方法,包括:

  1. 初始化回调(init method):在bean实例化后调用。
  2. 销毁回调(destroy method):在bean销毁前调用。

可以通过以下两种方式定义生命周期回调方法:

  1. 在XML配置中定义

    <bean id="exampleBean" class="com.example.ExampleBean" init-method="init" destroy-method="destroy" />
    
  2. 使用注解

    @Component
    public class ExampleBean {@PostConstructpublic void init() {// Initialization logic}@PreDestroypublic void destroy() {// Cleanup logic}
    }
    

结论

控制反转(IoC)和依赖注入(DI)是现代软件开发中重要的设计原则和模式。它们通过将依赖关系的管理交给外部容器,从而实现了低耦合、高可维护性和高可测试性的目标。Spring框架作为Java企业级开发的主流框架,通过其强大的IoC容器和丰富的配置方式,提供了全面的依赖注入支持,使开发者能够更加高效地构建复杂的应用程序。

理解IoC和DI的概念和原理,能够帮助开发者编写出更加模块化、可维护和易于测试的代码。在实际开发中,合理应用IoC和DI,可以显著提升代码质量和开发效率。

相关文章:

Spring常见问题一:IOC和DI

IOC和DI IOC和DI之间到底是什么关系&#xff1f; 什么是依赖关系&#xff1f;依赖关系会带来什么问题&#xff1f;Spring是怎么来支持依赖注入的&#xff1f; 引言 在现代软件开发中&#xff0c;面向对象编程&#xff08;OOP&#xff09;已经成为主流编程范式。然而&#xff0…...

LabVIEW红外热波图像缺陷检

开发使用LabVIEW开发的红外热波图像缺陷检测系统。该系统结合红外热像仪、工业相机和高效的数据采集硬件&#xff0c;实现对工件表面缺陷的自动检测和分析。通过LabVIEW的强大功能&#xff0c;系统能够实时采集、处理和显示红外热波图像&#xff0c;有效提高了检测的精度和效率…...

c#与欧姆龙PLC通信——如何更改PLC的IP地址

前言 我们有时候需要改变欧姆龙Plc的ip地址,下图有两种更改方式,一种是已知之前Plc设置的Ip地址,还有一种是之前不知道Pl的Ip地址是多少,下面分别做介绍。 1、已知PLC的IP地址的情况下更改地址 假设已知PLC的Ip地址,比如本文中PLC的IP为192.168.1.2,我首先将电脑的IP地…...

[Spring Boot]定时任务因系统时间修改之后无法执行

问题描述 当Spring Boot启动时&#xff0c;当前时间为2024-01-01 00:00:00。 此时你创建了任务&#xff1a; 每10秒钟触发一次定时任务 Scheduled(cron "0/10 * * * * ? ") public void scheduledTask() { }此时你手动修改了系统时间&#xff0c;修改为2023-12-0…...

【棋盘上的战舰】python刷题记录

目录 小前言 思路&#xff1a; 上代码 lucky ending 小前言 经过漫长的停更周期-----1个月 我决定铁血回归&#xff01;&#xff01;&#xff01; 思路&#xff1a; 两层for循环暴力最快了这种小小范围题&#xff0c;主要是第一行和第一列的边界处理&#xff0c;我分为…...

NoSQL 之Redis集群

Redis集群 主从复制 主从复制&#xff08;Replication&#xff09;是 Redis 中一种基本的高可用架构模式&#xff0c;适用于简单的读写分离需求和基本的故障恢复。在主从复制中&#xff0c;一个 Redis 主节点可以拥有多个从节点&#xff0c;主要特点包括&#xff1a; 角色定义&…...

ES13的4个改革性新特性

1、类字段声明 在 ES13 之前,类字段只能在构造函数中声明, ES13 消除了这个限制 // 之前 class Car {constructor() {this.color = blue;this.age = 2...

Flutter EasyRefresh:介绍与使用指南

什么是 Flutter EasyRefresh&#xff1f; Flutter EasyRefresh 是一个强大的下拉刷新和上拉加载组件&#xff0c;用于构建流畅且高效的 Flutter 应用程序。它提供了多种自定义配置和动画效果&#xff0c;使开发者可以轻松实现列表的刷新和加载功能。 主要功能 支持下拉刷新和…...

链表的回文结构(链表的中间节点+反转链表)

链表的回文结构 一.链表的中间节点思路1&#xff1a;暴力求解思路2&#xff1a;快慢指针 二.返回倒数第k个节点思路1&#xff1a;暴力求解思路2&#xff1a;快慢指针 三.反转链表思路1&#xff1a;头插法思路2&#xff1a;反转指针的指向 四.链表的回文结构思路1&#xff1a;利…...

汇编学习基础知识【记录】

前言 又是快乐的学习汇编的一天&#xff0c;时间如白驹过隙&#xff0c;抓紧时间&#xff0c;在学习能力最好的年纪多学习一些知识&#xff0c;朝着美好生活而奋斗&#xff01;哈哈哈 参考文章&#xff1a; https://blog.csdn.net/Z_H_Z_0/article/details/106574292 知识补…...

【持续集成_06课_Jenkins高级pipeline应用】

一、创建项目选择pipeline的风格 它主要是以脚本&#xff08;它自己的语言&#xff09;的方式进行运行&#xff0c;一般由运维去做的事情&#xff0c;作为测试而言。了解即可。 --- 体现形式全部通过脚本去实现&#xff1a;执行之前&#xff08;拉取代码&#xff09;执行&…...

taro小程序terser-webpack-plugin插件不生效(vue2版本)

背景 最近在做公司内部的小程序脚手架&#xff0c;为了兼容老项目和旧项目&#xff0c;做了vue2taro,vue3taro两个模板&#xff0c;发现terser-webpack-plugin在vue2和vue3中的使用方式并不相同&#xff0c;同样的配置在vue3webpack5中生效&#xff0c;但是在vue2webpack4中就…...

games103作业2(未完)

PBD方法 首先是每个质点的力的分析&#xff0c;不考虑碰撞和弹簧弹力的情况下&#xff0c;每个质点受重力的影响&#xff0c;所以需要对每个质点进行速度和位置的重力影响更新。 float t 0.0333f; float damping 0.99f; int[] E; float[] L; Vector3[] V; Vector3 gra…...

避免 WebSocket 连接被拒绝

一、检查服务器配置和权限 (一)确认服务器访问权限 确保您的客户端有访问服务器的合法权限。如果服务器设置了访问控制列表(ACL)或仅允许特定的源(Origin)进行连接,您需要确保客户端的请求来源在允许的范围内。例如,如果服务器只允许来自特定域名的连接,而您的客户端从…...

shell中关于数组的使用

shell中关于数组的使用 在Shell中&#xff0c;数组是一种可以存储多个值的变量。数组的每个值都由一个数字索引来访问。在Shell中&#xff0c;数组的索引从0开始。 数组的常见的使用方法包括 数组的定义数组的打印数组长度数组的遍历数组元素的打印数组元素的添加数组元素的…...

python:绘制一元三次函数的曲线

编写 test_x3_3x.py 如下 # -*- coding: utf-8 -*- """ 绘制函数 y x^33x4 在 -3<x<3 的曲线 """ import numpy as np from matplotlib import pyplot as plt# 用于正常显示中文标题&#xff0c;负号 plt.rcParams[font.sans-serif] […...

SAP PP学习笔记26 - User Status(用户状态)的实例,订单分割中的重要概念 成本收集器,Confirmation(报工)的概述

上面两章讲了生产订单的创建以及生产订单的相关内容。 SAP PP学习笔记24 - 生产订单&#xff08;制造指图&#xff09;的创建_sap 工程外注-CSDN博客 SAP PP学习笔记25 - 生产订单的状态管理(System Status(系统状态)/User Status(用户状态)),物料的可用性检查&#xff0c;生…...

ctfshow-web入门-php特性(web104-web108)

目录 1、web104 2、web105 3、web106 4、web107 5、web108 1、web104 需要传入的 v1 和 v2 进行 sha1 加密后相等。 解法1&#xff1a; 这里都没有判断 v1 和 v2 是否相等&#xff0c;我们直接传入同样的内容加密后肯定也一样。 ?v21 post&#xff1a; v11 拿到 flag…...

python之集合相关

1.概况 是无序的数据结构 集合内的个体统称为元素&#xff0c;每个元素不可重复 所有元素被放在大括号里面&#xff0c;元素之间通过逗号分隔 集合对象是一组无序的可哈希的值&#xff0c;集合元素是不可变的数据类型 2.定义集合 使用大括号语法 基本语法&#xff1a; {元素1&a…...

【学习笔记】无人机(UAV)在3GPP系统中的增强支持(十一)-无人机服务可用性用例需求

引言 本文是3GPP TR 22.829 V17.1.0技术报告&#xff0c;专注于无人机&#xff08;UAV&#xff09;在3GPP系统中的增强支持。文章提出了多个无人机应用场景&#xff0c;分析了相应的能力要求&#xff0c;并建议了新的服务级别要求和关键性能指标&#xff08;KPIs&#xff09;。…...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻

在如今就业市场竞争日益激烈的背景下&#xff0c;越来越多的求职者将目光投向了日本及中日双语岗位。但是&#xff0c;一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧&#xff1f;面对生疏的日语交流环境&#xff0c;即便提前恶补了…...

基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销&#xff0c;平衡网络负载&#xff0c;延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】

微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来&#xff0c;Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩

目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

生成 Git SSH 证书

&#x1f511; 1. ​​生成 SSH 密钥对​​ 在终端&#xff08;Windows 使用 Git Bash&#xff0c;Mac/Linux 使用 Terminal&#xff09;执行命令&#xff1a; ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" ​​参数说明​​&#xff1a; -t rsa&#x…...

九天毕昇深度学习平台 | 如何安装库?

pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子&#xff1a; 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...

Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信

文章目录 Linux C语言网络编程详细入门教程&#xff1a;如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket&#xff08;服务端和客户端都要&#xff09;2. 绑定本地地址和端口&#x…...

搭建DNS域名解析服务器(正向解析资源文件)

正向解析资源文件 1&#xff09;准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2&#xff09;服务端安装软件&#xff1a;bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...

iview框架主题色的应用

1.下载 less要使用3.0.0以下的版本 npm install less2.7.3 npm install less-loader4.0.52./src/config/theme.js文件 module.exports {yellow: {theme-color: #FDCE04},blue: {theme-color: #547CE7} }在sass中使用theme配置的颜色主题&#xff0c;无需引入&#xff0c;直接可…...

【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看

文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...