IoC设计模式详解:控制反转的核心思想

前言:在软件开发中,设计模式是一种经过验证的、在特定场景下能有效解决问题的解决方案。控制反转(Inversion of Control,IoC) 作为一种设计模式,通过让程序的控制流和对象管理反转,从而使得代码的解耦性和可维护性大大提高。
学习Spring,其中一个核心——Spring IoC容器,则是这一模式在Spring框架中的具体实现。

一、IoC简介

IoC(控制反转)是一种设计模式(原则),核心思想是将对象的创建、初始化和依赖关系的管理从程序中反转出来,交由外部容器(例如 Spring)来负责。

也就是说,程序不再控制对象的创建和生命周期,而是通过外部容器来进行管理,这样可以实现更高的解耦和灵活性。

1d8ce4dd-a4ea-4e26-93ea-c3d26dda88c6

控制反转显然是一个抽象的概念,举一个鲜明的例子来说明:

在现实生活中,人们要用到一样东西的时候,第一反应就是去找到这件东西,比如想喝新鲜橙汁,在没有饮品店的日子里,最直观的做法就是:买果汁机、买橙子,然后准备开水。值得注意的是:这些都是你自己 “主动”创造的过程,也就是说一杯橙汁需要你自己创造。

然而到了今时今日,由于饮品店的盛行,当我们想喝橙汁时,第一想法就转换成了找到饮品店的联系方式,通过电话等渠道描述你的需要、地址、联系方式等,下订单等待,过一会儿就会有人送来橙汁了。

image

请注意你并没有“主动”去创造橙汁,橙汁是由饮品店创造的,而不是你,然而也完全达到了你的要求,甚至比你创造的要好上那么一些。

所以控制反转IoC(Inversion of Control)是说创建对象的控制权进行转移,以前创建对象的主动权和创建时机是由自己把控的,而现在这种权力转移到第三方,比如转移交给了IoC容器,它就是一个专门用来创建对象的工厂,你要什么对象,它就给你什么对象,有了 IoC容器,依赖关系就变了,原先的依赖关系就没了,它们都依赖IoC容器了,通过IoC容器来建立它们之间的关系。

二、发展

IoC(Inversion of Control,控制反转)设计原则的发展历程反映了软件工程领域中对解耦合、模块化和可测试性的不断追求。以下是IoC设计理念从萌芽到成熟的主要发展阶段:

1. 早期探索与概念形成
  • 20世纪80年代至90年代初:在面向对象编程(OOP)逐渐普及的背景下,开发者开始意识到直接在代码中创建和管理依赖会导致高度耦合的问题。此时,一些先驱者开始思考如何将这种控制权转移给外部组件或框架。
  • MVC模式:Model-View-Controller架构是最早体现IoC思想的设计模式之一,它通过分离关注点来实现一定程度上的解耦。
2. IoC概念的正式提出
  • 1996年:Michael Mattson在他的论文《Object-Oriented Frameworks: A Survey》中首次使用了“控制反转”这个术语,用来描述框架如何接管应用程序的主控流程。

  • 2004年:Martin Fowler在其文章《Inversion of Control Containers and the Dependency Injection pattern》中详细阐述了IoC的概念,并引入了“依赖注入”(Dependency Injection, DI)这一术语作为IoC的具体实现方式。这篇文章极大地推动了DI模式的流行。

    image

​ ”软件开发教父“—Martin Fowler

3. 框架与工具的支持
  • Spring框架的崛起:Spring于2004年发布,迅速成为Java企业级应用开发中最受欢迎的框架之一。Spring的核心特性之一就是其强大的IoC容器,它不仅实现了基本的DI功能,还提供了丰富的配置选项和生命周期管理机制。
  • 其他框架:除了Spring,还有许多其他框架也采用了IoC/DI模式,如PicoContainer、Guice(Google推出的轻量级Java依赖注入框架)、以及.NET平台下的Ninject等。这些框架进一步促进了IoC理念在不同编程语言和技术栈中的传播。
4. 扩展与深化
  • AOP集成:随着面向切面编程(Aspect-Oriented Programming, AOP)的发展,IoC容器开始支持AOP特性,允许开发者以声明式的方式定义横切关注点(如日志记录、事务管理),从而进一步减少了代码中的重复劳动。
  • 事件驱动架构:现代应用越来越多地采用事件驱动的方式进行组件间通信,而IoC容器提供的事件发布/订阅机制正好满足了这一需求,使得系统更加灵活且易于扩展。
  • 微服务架构:在微服务架构中,每个服务都是独立部署的单元,它们之间的交互通常通过API网关或消息队列完成。在这种情况下,IoC容器的作用变得更加重要,因为它可以帮助管理和协调各个服务之间的依赖关系。
5. 当前趋势与发展
  • 函数式编程与响应式编程:随着函数式编程语言(如Scala、Clojure)以及响应式编程模型(Reactive Programming)的兴起,IoC/DI模式也在不断演进,以适应新的编程范式。例如,在响应式流处理中,依赖注入可以用于简化异步操作和背压管理。
  • 云原生应用:在云环境中,服务发现、配置管理等功能变得至关重要。IoC容器可以通过集成服务注册中心(如Eureka、Consul)和分布式配置管理系统(如Spring Cloud Config),为云原生应用提供动态的依赖管理和配置更新能力。
  • Serverless架构:无服务器计算模式下,函数即服务(FaaS)平台自动管理资源分配和扩展。尽管在这种环境下不再需要传统的IoC容器,但类似的思想仍然适用于定义和管理函数之间的依赖。

三、特点

IOC(Inversion of Control,控制反转)设计模式 是一种通过将对象的创建和依赖关系管理交给外部容器来实现松耦合的设计模式。它通过依赖注入(DI)等方式解耦系统中的组件,从而提升系统的可扩展性、可维护性和测试性。然而,像任何设计模式一样,IOC模式也有其优缺点。

优点
  1. 降低耦合度

    • IOC通过将依赖关系交给容器管理,避免了类与类之间的紧耦合。类之间不需要知道对方的具体实现,减少了模块之间的依赖,提高了系统的灵活性和可扩展性。
  2. 提高代码的可维护性

    • 由于类不再直接管理其依赖关系,修改某个组件的实现不会直接影响到其他组件。这使得系统更容易维护,尤其是在大型系统中,修改或替换某个依赖时,不需要修改应用程序的其他部分。
  3. 增强代码的可测试性

    • IOC容器通过依赖注入的方式将依赖项外部化,便于进行单元测试。在测试过程中,可以轻松地替换实际的依赖项为mock对象或模拟实现,独立地测试每个模块。
  4. 提升系统的灵活性和可扩展性

    • IOC容器提供了更为灵活的依赖关系配置。通过配置文件或注解方式,开发者可以在不修改代码的情况下替换不同的实现或改变依赖关系,从而增强系统的扩展性。
  5. 集中式管理对象生命周期

    • IOC容器负责对象的创建、管理和销毁,开发人员无需关注对象的生命周期和依赖关系的维护,从而简化了代码结构。
  6. 符合“面向接口编程”原则

    • IOC设计模式鼓励通过接口来定义依赖,而不是依赖于具体的实现类。这不仅提升了系统的灵活性,也使得系统可以更容易地进行替换和扩展。
  7. 有助于实现设计模式和最佳实践

    • IOC设计模式通常与其他设计模式(如工厂模式、策略模式等)配合使用,使得系统的设计更加规范,符合常见的设计最佳实践。

缺点
  1. 学习曲线陡峭

    • IOC和依赖注入(DI)虽然能带来很大的灵活性,但需要开发者对IOC容器、依赖注入以及相关的配置方式有一定的理解和掌握。在一些小型项目或团队中,过度使用IOC可能会带来额外的学习成本和开发复杂度。
  2. 增加系统的复杂性

    • 在使用IOC时,系统的结构变得更加抽象,特别是在没有合理的设计规范时,可能导致过度依赖配置或容器,导致系统的复杂性增加。
    • 例如,多个服务的依赖关系可能通过不同的配置文件或注解来管理,如果管理不当,可能导致系统难以理解和调试。
  3. 性能开销

    • 由于IOC容器负责对象的管理和依赖注入,容器在初始化阶段会进行对象的创建和依赖解析,可能会引入额外的性能开销,尤其是在大型应用中,启动时会有一定的延迟。
    • 此外,反射机制(如果使用)也会影响性能,虽然这种影响通常是微不足道的,但在一些高性能要求的场景中可能需要谨慎考虑。
  4. 调试和跟踪困难

    • 由于IOC容器负责管理对象的生命周期和依赖关系,调试时可能不易追踪依赖关系和对象的创建过程。尤其是在大型应用中,依赖关系可能变得非常复杂,不容易找到对象之间的依赖路径和问题所在。
    • 此外,依赖注入的配置错误(如错过某个依赖)可能导致应用启动失败,排查这些错误有时会变得复杂。
  5. 过度使用可能导致设计问题

    • 虽然IOC可以有效解耦,但在某些场景中,过度使用IOC可能会导致设计不够清晰。比如,如果没有合理的接口和模块划分,依赖注入可能会导致大量的配置和接口,反而增加了系统的复杂度。
    • 如果不加以控制,过度的依赖注入和反转控制可能让代码结构变得难以理解和维护。
  6. 隐式依赖

    • 在一些复杂的IOC实现中,依赖注入可能是隐式的,这意味着开发者可能并不直接看到某个类所依赖的所有对象。在这种情况下,阅读和理解代码可能需要花费额外的时间,尤其是当依赖关系非常复杂时。
  7. 可能增加配置和管理工作

    • 使用IOC容器通常需要大量的配置(如XML文件或注解配置)来管理对象的创建和依赖注入。如果容器配置不当,可能导致配置文件变得非常庞大和复杂,影响代码的清晰度和维护性。

四、实现方式

常见的 IOC 实现方式: 依赖注入(Dependency Injection, DI):最常用的 IOC 实现方式,容器通过构造函数、属性或方法来注入对象的依赖。 服务定位(Service Locator):通过集中管理的方式,容器提供一个访问接口,让程序员通过此接口获取到需要的依赖。

IOC(Inversion of Control,控制反转) 是一种设计模式,它的核心思想是将控制对象创建和依赖关系管理的责任从类内部转移到外部容器中。实现IOC的方式有多种,常见的主要有以下几种:

1. 依赖注入(Dependency Injection, DI)

依赖注入是IOC实现的主要方式之一。它通过将类的依赖关系(即对象的引用)交给外部容器来管理,从而减少类之间的耦合。

依赖注入有三种方式

  • 构造器注入(Constructor Injection)
    依赖通过构造器传入。在对象创建时,IOC容器会通过构造函数将依赖注入到目标对象中。

    public class Service {private final Repository repository;// 依赖通过构造器注入public Service(Repository repository) {this.repository = repository;}public void execute() {repository.doSomething();}
    }
    
  • Setter注入(Setter Injection)
    依赖通过类的setter方法注入。IOC容器会通过反射调用setter方法为类提供所需的依赖。

    public class Service {private Repository repository;// 通过setter方法注入依赖public void setRepository(Repository repository) {this.repository = repository;}public void execute() {repository.doSomething();}
    }
    
  • 接口注入(Interface Injection)
    依赖通过接口注入。实现特定接口的类会提供一个方法,允许外部容器注入依赖。

    public interface RepositoryAware {void setRepository(Repository repository);
    }public class Service implements RepositoryAware {private Repository repository;@Overridepublic void setRepository(Repository repository) {this.repository = repository;}public void execute() {repository.doSomething();}
    }
    

2. 依赖查找(Dependency Lookup)

依赖查找是IOC的另一种实现方式,其中对象本身没有直接接收依赖,而是通过查找容器来获取其依赖。依赖查找通常通过容器的API来获取需要的对象。

  • 查找容器:应用程序通过容器API获取依赖对象。
   public class Service {private ApplicationContext context;public Service(ApplicationContext context) {this.context = context;}public void execute() {// 依赖查找Repository repository = (Repository) context.getBean(Repository.class);repository.doSomething();}}

依赖查找虽然能实现IOC的目的,但它往往较为依赖容器,且不如依赖注入(DI)方式灵活,因为它涉及到容器的显式调用,违反了“松耦合”的原则。

3. Service Locator

Service Locator模式是一种经典的IOC实现方式。通过一个中央的服务定位器(Service Locator),对象可以在运行时获取依赖。Service Locator实际上是依赖查找的一个变体。

在这种方式中,类通过调用一个服务定位器来查找并获取它所需要的依赖对象。

   public class Service {public void execute() {Repository repository = ServiceLocator.getRepository();repository.doSomething();}}

缺点

  • Service Locator模式和依赖查找类似,容易使代码过于依赖容器,违反了松耦合的原则。
  • 难以进行单元测试,因为它隐藏了类的依赖关系。

4. 使用框架实现IOC

目前,大多数IOC的实现都是通过一些流行的框架来实现的,最典型的框架包括:

  • Spring Framework
    Spring是一个非常流行的Java框架,它通过依赖注入和AOP(面向切面编程)实现了强大的IOC容器。Spring可以通过XML配置、注解配置或者Java配置来实现IOC,自动管理对象的创建、生命周期和依赖注入。

    • XML配置方式

      <bean id="service" class="com.example.Service"><constructor-arg ref="repository"/>
      </bean><bean id="repository" class="com.example.Repository"/>
      
    • 注解配置方式

      @Component
      public class Service {private final Repository repository;@Autowiredpublic Service(Repository repository) {this.repository = repository;}
      }@Component
      public class Repository {public void doSomething() {// ...}
      }
      

    在Spring中,IOC容器会负责对象的实例化、依赖注入以及生命周期管理。

  • Guice (Google)
    Guice是Google推出的一个轻量级的DI框架,主要用于Java应用。它同样实现了IOC,使用注解和接口实现依赖注入,支持构造器注入、方法注入等多种方式。

    public class Service {private final Repository repository;@Injectpublic Service(Repository repository) {this.repository = repository;}
    }
    
  • Dagger
    Dagger是一个静态依赖注入框架,广泛用于Android应用开发中。它通过代码生成的方式来实现依赖注入,性能较高。

    @Component
    public interface ServiceComponent {Service getService();
    }@Module
    public class ServiceModule {@Providespublic Repository provideRepository() {return new Repository();}
    }
    

5. 反射机制

在一些情况下,IOC容器使用反射机制动态创建对象并注入依赖。反射机制允许在运行时确定类的构造函数、字段和方法,从而实现依赖注入。

  • 反射实例化:在没有框架支持的情况下,可以手动使用反射创建对象并注入依赖。
   Constructor<?> constructor = Service.class.getConstructor(Repository.class);Service service = (Service) constructor.newInstance(repository);

注意:反射带来的性能开销较大,不推荐过度使用。

总结

IOC的实现方式多种多样,最常见的有依赖注入(DI)、依赖查找和Service Locator等方式。在现代开发中,使用框架(如Spring、Guice等)是最常见的方式,它们通过提供IOC容器来自动管理对象的创建、生命周期和依赖注入。依赖注入通常被认为是最优的IOC实现方式,因为它能够有效地解耦系统,提升系统的可维护性和测试性。

五、应用场景

IOC 主要用于 解耦 组件、提高灵活性可维护性,其典型应用场景包括:

1. 大型企业级应用开发

在大型应用中,各个模块和组件之间的依赖关系通常非常复杂。通过使用 IOC,可以将这些依赖关系交给外部容器(如 Spring 框架)来管理,从而降低系统的耦合度,使得系统更容易扩展和维护。

场景举例

  • 开发企业级管理系统(如 ERP 系统、CRM 系统等)时,可能涉及多个服务、数据访问层和业务逻辑层,通过 IOC 容器可以方便地注入依赖,进行灵活的模块化和配置。

2. 组件化和插件化的架构

在需要实现插件化或可扩展架构的应用中,IOC 可以帮助动态加载和管理不同的插件或模块。通过定义接口和注入不同的实现类,系统能够在运行时根据配置和需要灵活加载不同的组件。

场景举例

  • 在一个支持多种数据库的应用中,不同的数据库驱动实现可以作为插件模块,在启动时通过 IOC 容器注入和切换。
  • 在支付系统中,不同的支付方式(如支付宝、微信支付、银联等)可以作为插件模块,在运行时动态注入。

3. 跨平台开发

在跨平台开发中,不同平台的实现可能会有所不同。通过 IOC,可以将平台相关的实现与平台无关的业务逻辑解耦,使得相同的业务逻辑能够在多个平台上共享。

场景举例

  • 在 Android 和 iOS 平台上开发应用时,可以通过 IOC 将平台相关的代码(如网络请求、文件存储等)与平台无关的业务逻辑解耦,使得相同的业务逻辑代码在不同平台之间共享。

4. 单元测试与Mock

在进行单元测试时,使用 IOC 可以更方便地替换和模拟组件依赖,从而实现更高效的测试。通过 IOC 注入假对象(Mock 对象),可以让测试更加集中在某一单一组件的行为上,而不依赖于其实际的依赖。

场景举例

  • 进行单元测试时,可以用 Mock 对象替代数据库访问层、外部服务等,确保测试只关注业务逻辑本身。

5. Web 应用开发

在 Web 应用开发中,尤其是使用 MVC 架构的应用中,IOC 是非常重要的。通过 IOC 容器,Web 应用可以轻松地管理控制器、服务层和数据访问层之间的依赖关系。Spring MVC 就是通过 IOC 实现了控制器、服务和 DAO 的依赖注入,使得 Web 应用更加松耦合、易于维护。

场景举例

  • 在开发一个 Web 应用时,可以通过 IOC 容器注入控制器(Controller)和服务层(Service),将视图(View)与业务逻辑(Service)和数据层(Repository)解耦,从而简化了 Web 应用的开发和扩展。

6. 异步任务和消息队列

在处理异步任务、消息队列和事件驱动架构时,IOC 可以帮助简化事件处理的注册和触发。使用 IOC 容器管理任务和事件的监听器,可以使得事件和任务处理模块之间的依赖关系更加灵活。

场景举例

  • 在分布式系统中,使用消息队列(如 RabbitMQ、Kafka 等)来异步处理任务时,可以通过 IOC 注入消息处理类,使得消息处理逻辑与其他业务逻辑解耦,提高系统的可扩展性。

在本文中,我们深入探讨了IoC(控制反转)设计模式及其在现代软件开发中的应用。通过引入IoC,我们能够有效地降低模块间的耦合度,提高系统的灵活性和可维护性。希望这些知识对你有所帮助,并能在实际开发中灵活应用,打造更加高效和优雅的代码架构。

3ec794dacde34583aafafe15b1490012

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

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

相关文章

Swift White Hawkstrider

Swift White Hawkstrider 迅捷白色陆行鸟 Swift White Hawkstrider - Item - 魔兽世界怀旧服TBC数据库_WOW2.43数据库_70级《燃烧的远征》数据库 Kaelthas Sunstrider (1) <Lord of the Blood Elves> 凯尔萨斯逐日者. 掉落 [80圣骑士][Alonsus-加丁][诺森德冒险补给品…

2025 年前端新技术如何塑造未来开发生态?

开发领域&#xff1a;前端开发 | AI 应用 | Web3D | 元宇宙 技术栈&#xff1a;JavaScript、React、ThreeJs、WebGL、Go 经验经验&#xff1a;6 年 前端开发经验&#xff0c;专注于图形渲染和 AI 技术 开源项目&#xff1a;AI智简未来、晓智元宇宙、数字孪生引擎 大家好&#x…

2024 年 MySQL 8.0.40 安装配置、Workbench汉化教程最简易(保姆级)

首先到官网上下载安装包&#xff1a;http://www.mysql.com 点击下载&#xff0c;拉到最下面&#xff0c;点击社区版下载 windows用户点击下面适用于windows的安装程序 点击下载&#xff0c;网络条件好可以点第一个&#xff0c;怕下着下着断了点第二个离线下载 双击下载好的安装…

在大型语言模型LLM中使用私有数据

目录 一、说明 二、训练&#xff1f; 三、及时工程 四、构建系统提示 五、数据人性化 六、我的数据安全吗&#xff1f; 一、说明 随着 2023 年大型语言模型的大规模兴起&#xff0c;许多“基于对话”的服务应运而生&#xff0c;使用户能够通过自然对话与数据和其他产品进行交互…

字玩FontPlayer开发笔记6 Tauri2设置菜单

字玩FontPlayer开发笔记6 Tauri2设置菜单 字玩FontPlayer是笔者开源的一款字体设计工具&#xff0c;使用Vue3 ElementUI开发&#xff0c;源代码&#xff1a; github: https://github.com/HiToysMaker/fontplayer gitee: https://gitee.com/toysmaker/fontplayer 笔记 字玩目…

Chapter4.1 Coding an LLM architecture

文章目录 4 Implementing a GPT model from Scratch To Generate Text4.1 Coding an LLM architecture 4 Implementing a GPT model from Scratch To Generate Text 本章节包含 编写一个类似于GPT的大型语言模型&#xff08;LLM&#xff09;&#xff0c;这个模型可以被训练来生…

linux-centos-安装miniconda3

参考&#xff1a; 最新保姆级Linux下安装与使用conda&#xff1a;从下载配置到使用全流程_linux conda-CSDN博客 https://blog.csdn.net/qq_51566832/article/details/144113661 Linux上删除Anaconda或Miniconda的步骤_linux 删除anaconda-CSDN博客 https://blog.csdn.net/m0_…

Speech Recognition vs. Voice Recognition | 语音识别工作原理 | 模型训练 | 应用

注&#xff1a;机翻&#xff0c;未校。 Speech Recognition 与 Voice Recognition 剑桥词典 speech recognition&#xff0c;语音识别 voice recognition&#xff0c;声音识别 Speech vs. Voice - What’s the Difference? | This vs. That https://thisvsthat.io/speech-vs…

外网访问本地部署的 VMware ESXi 服务

本文将详细的介绍如何在本地部署的 VMware ESXi 以及结合路由侠内网穿透技术&#xff0c;实现外网远程访问和管理本地 ESXi 服务器的具体步骤和配置方法。 第一步&#xff0c;本地部署 VMware ESXi 1&#xff0c;先去官网下载 ESXI &#xff1a;网址&#xff1a;Home - Suppor…

如何配置【Docker镜像】加速器+【Docker镜像】的使用

一、配置Docker镜像加速器 1. 安装/升级容器引擎客户端​ 推荐安装1.11.2以上版本的容器引擎客户端 2. 配置镜像加速器​ 针对容器引擎客户端版本大于1.11.2的用户 以root用户登录容器引擎所在的虚拟机 修改 "/etc/docker/daemon.json" 文件&#xff08;如果没有…

基于Spring Boot的车辆违章信息管理系统(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…

如何提高软件研发效率?

如何提高软件研发效率&#xff1f; 概述 莫等闲&#xff0c;白了少年头&#xff0c;空悲切。近些年来在大家眼里形成了“卷王”的印象&#xff0c;第一次听到这一的评价感觉有点不好意思&#xff0c;之后回想感觉挺自豪的&#xff0c;说明现在的我没有浪费光阴&#xff0c;我一…

jenkins入门--安装jenkins

下载地址https://www.jenkins.io/ jdk 安装 &#xff1a;Jenkins需要安装对应版本的jdk,我在安装过程中显示需要21,17 Java Downloads | Oracle jenkins安装过程参考全网最清晰Jenkins安装教程-windows_windows安装jenkins-CSDN博客 安装完成后&#xff0c;浏览器输入127.0.…

单片机-独立按键矩阵按键实验

1、按键介绍 按键管脚两端距离长的表示默认是导通状态&#xff0c;距离短的默认是断开状态&#xff0c; 如果按键按下&#xff0c;初始导通状态变为断开&#xff0c;初始断开状态变为导通 我们开发板是采用软件消抖&#xff0c;一般来说一个简单的按键消抖就是先读取按键的状…

一文详解YOLOv8多模态目标检测(可见光+红外图像,基于Ultralytics官方代码实现),轻松入门多模态检测领域!

目录 1. 文章主要内容2. 相关说明3. 基于YOLOv8的多模态目标检测3.1 启动运行YOLOv8多模态代码3.2 详解代码流程&#xff08;重点&#xff09;3.2.1 train.py文件&#xff08;入口&#xff09;3.2.2 engine\model.py文件3.2.3 engine\trainer.py文件3.2.4 models\yolo\detect\t…

【顶刊TPAMI 2025】多头编码(MHE)之极限分类 Part 3:算法实现

目录 1 三种多头编码&#xff08;MHE&#xff09;实现1.1 多头乘积&#xff08;MHP&#xff09;1.2 多头级联&#xff08;MHC&#xff09;1.3 多头采样&#xff08;MHS&#xff09;1.4 标签分解策略 论文&#xff1a;Multi-Head Encoding for Extreme Label Classification 作者…

【AWS SDK PHP】This operation requests `sigv4a` auth schemes 问题处理

使用AWS SDK碰到的错误&#xff0c;其实很简单&#xff0c;要装个扩展库 保持如下 Fatal error: Uncaught Aws\Auth\Exception\UnresolvedAuthSchemeException: This operation requests sigv4a auth schemes, but the client currently supports sigv4, none, bearer, sigv4-…

LLM - 使用 LLaMA-Factory 部署大模型 HTTP 多模态服务 教程 (4)

欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://spike.blog.csdn.net/article/details/144881432 大模型的 HTTP 服务,通过网络接口,提供 AI 模型功能的服务,允许通过发送 HTTP 请求,交互大模型,通常基于云计算架构,无需在本地部署复杂的模型和硬件,…

【MATLAB】【Simulink仿真】向模型中添加自定义子系统

一、子系统的创建 1、启动Simulink&#xff0c;选择【新建】——【空白子系统】——【创建子系统】 2、选择【浏览组件库】&#xff0c;创建使能子系统。 3、保存至当前工作目录。 二、建立模型仿真 1、启动Simulink&#xff0c;选择【新建】——【空白子系统】——【创建子系…

HTML——56.表单发送

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>表单发送</title></head><body><!--注意&#xff1a;1.表单接收程序&#xff0c;放在服务器环境中(也就是这里的www文件目录中)2.表单发送地址&#x…