IOC容器和依赖注入

如何使用PHP构建IoC容器,实现依赖注入! IoC 容器(控制反转容器)是一个用于管理应用中对象生命周期和依赖关系的工具。在传统的面向对象编程中,类与类之间的依赖关系通常是直接由开发者在代码中显式管理的。IoC 容器的核心思想是控制反转,即容器会接管对象的实例化及依赖注入过程,而不需要我们显式地创建依赖对象。首先,创建一个Container类来管理依赖关系。我们需要一个bind方法来绑定类和它的依赖,和一个resolve方法来解析和实例化类。php// 存储所有绑定的服务// 绑定一个服务// 解析服务并返回实例if (!$name。 阅读详情

1 依赖倒置

依赖倒置的核心价值:
如果没有依赖倒置,全部都是依赖细节,如果分层架构是 A层---B层--C层---D层---E层---F层,下层的修改,可能会导致上层随之改变,F层如果改变,E层要改,D层要改,C层要改......影响很大,成水波式向上影响,架构就的极度不稳定。
如果都是依赖于抽象的,抽象即接口或抽象类。 抽象是相对稳定的,修改下层不会影响上层。因为上层不是依赖于具体的,这让我们的代码更加稳定。
IOC 控制对象的创建,不就是完全控制了对象的创建吗?所以,IOC的本质是工厂。
既然IOC是工厂,那么工厂生产产品就是创建对象。

2 简单工厂创建对象会不会有什么问题呢?

工厂创建对象,如果对象没有无参数构造函数,必须得按照构造函数参数的要求,准备好构造函数。那就会出现问题:如果对象存在层层依赖,有多少层依赖,就得准备多少个方法。
要解决这个问题,我们就有了这样的一个目标:如果有依赖的,能够做到,在创建对象的时候,能够自动把对象依赖的对象给创建出来,然后传递进去,这样就很好。
Asp.Net Core的内置IOC容器可以帮助我们解决掉这个问题。

3 内置IOC容器

需要引入Microsoft.Extensions.DependencyInjection包。
Zlt.IOC.Interfaces 命名空间下创建接口:

public interface IHeadphone
{
}
public interface IMicrophone
{
}   
public interface IPower
{
}
public interface IPhone
{
    void Call();
    void Init123456678890(IPower iPower);
    IMicrophone Microphone { get; set; }
    IHeadphone Headphone { get; set; }
    IPower Power { get; set; }
}

Zhaoxi.IOC.Services 实现接口:

public class Headphone : IHeadphone
    { 
        public Headphone()
        {
            Console.WriteLine($"{this.GetType().Name}被构造。。");
        } 
    }
    public class Headphone : IHeadphone
    {
        public Headphone()
        {
            Console.WriteLine($"{GetType().Name}被构造。。");
        }
    }
    public class Microphone : IMicrophone
    {
        public IHeadphone _IHeadphone { get; set; }

        public IHeadphone _IHeadphoneField;

        public void SetHeadphone(IHeadphone headphone)
        {
            _IHeadphoneField = headphone;
        }

        /// <summary>
        /// 没有无参数构造函数
        /// </summary>
        /// <param name="headphone"></param>
        [SelectCtor]
        public Microphone(IHeadphone headphone)
        {
            Console.WriteLine($"{GetType().Name}被构造。。");
        }

        public Microphone(IHeadphone headphone, IHeadphone headphone1)
        {
            Console.WriteLine($"{GetType().Name}被构造。。");
        }
    }
    public class Power : IPower
    {
        public Power(IMicrophone microphone)
        {
            Console.WriteLine($"{GetType().Name}被构造。。");
        }
    }
    public class AndroidPhone : IPhone
    {
        public IMicrophone Microphone { get; set; }
        public IHeadphone Headphone { get; set; }
        public IPower Power { get; set; }

        public AndroidPhone(IPower Power)
        {
            Power = Power;
            Console.WriteLine("{0}构造函数", GetType().Name);
        }

        public void Call()
        {
            Console.WriteLine("{0}打电话", GetType().Name); ;
        }

        public void Init123456678890(IPower iPower)
        {
            Power = iPower;
        }
    }

调用:

//1.IOC容器的实例
ServiceCollection services = new();
//2.注册抽象和具体之间的关系
services.AddTransient<IHeadphone, Headphone>();
services.AddTransient<IMicrophone, Microphone>();
services.AddTransient<IPower, Power>();
services.AddTransient<IPhone, AndroidPhone>();
//3.Buidl下得到一个Provider
ServiceProvider serviceProvider = services.BuildServiceProvider();
//4.创建对象
IHeadphone headphone = serviceProvider.GetService<IHeadphone>();
IMicrophone microphone = serviceProvider.GetService<IMicrophone>();
IPower power = serviceProvider.GetService<IPower>();
IPhone iphone = serviceProvider.GetService<IPhone>();

这就是框架的依赖注入,如果对象A依赖于对象B,对象B依赖于对象C,在创建对象A时,自动先创建对象C,满足对象B的依赖,再创建对象B,满足A的依赖,最后创建出对象A。

4 依赖注入DI

内置容器中,仅支持构造函数注入这一种。依赖注入有3中。

  1. 构造函数注入:如果对象A在构造函数中依赖于对象B,对象B在构造函数中依赖于对象C,如果要构造对象A,自动构造C,传入对象B的构造函数,构造出对象B,传入对象A,构造出对象A;
  2. 属性注入:如果对象A在属性中依赖于对象B,对象B在属性中依赖于对象C,如果要构造对象A,在构造出对象A之后,检测属性,如果属性有依赖,就自动的去创建依赖的对象,创建出来以后,赋值给对象A中共的属性; 如果在创建的过程中,还有依赖,就继续创建
  3. 方法注入:如果对象A在某个方法中依赖于对象B,对象B在某个方法中依赖于对象C,如果要构造对象A,在构造出对象A之后,检测某个方法,如果某个方法的参数有依赖,就自动的去创建某个方法参数依赖的对象,创建出来以后,去执行这个方法,把构造出来的对象传递给这方法的参数; 如果在创建的过程中,还有方法依赖,就继续创建。

5 这个 IOC 和依赖注入 DI 之间,是什么关系?

IOC 是架构设计的一种方案,一种目标;
DI 是实现 IOC 容器的的时候,一种解决依赖问题的技术手段;

6 底层究竟如何实现?

下面就是关于IOC底层的构造函数注入的核心逻辑。
Zlt.IOC.Common 提供公共方法:

public interface IMyServiceCollection
{
    /// <summary>
    /// 注册具体和抽象之间的关系
    /// </summary>
    /// <typeparam name="T">抽象</typeparam>
    /// <typeparam name="S">具体</typeparam>
    public void Register<T, S>() where S : T;
    /// <summary>
    /// 获取对象的实例
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    public T GetService<T>();
}
public class MyServiceCollection : IMyServiceCollection
{
    private static Dictionary<string, Type> MapDic = new Dictionary<string, Type>();
    /// <summary>
    ///  保存  注册具体和抽象之间的关系
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <typeparam name="S"></typeparam>
    public void Register<T, S>() where S : T
    {
        MapDic.Add(typeof(T).FullName, typeof(S));
    }
    /// <summary>
    ///  获取对象的实例
    /// </summary>
    /// <typeparam name="T">参数:必然是抽象</typeparam>
    /// <returns></returns>
    public T GetService<T>()
    {
        string abstractFullName = typeof(T).FullName;
        Type type = MapDic[abstractFullName];
        return (T)CreateInstance(type);
    }
    /// <summary>
    /// 创建对象 有依赖的递归创建
    /// </summary>
    /// <param name="type"></param>
    /// <returns></returns>
    public object CreateInstance(Type type)
    {
        ConstructorInfo? ctor = type.GetConstructors()
            .Where(a => a.IsDefined(typeof(SelectCtorAttribute)))
            .FirstOrDefault();
        if (ctor == null)
        {
            ctor = type.GetConstructors()
                .OrderByDescending(c => c.GetParameters().Length)
                .First();
        }
        List<object> parametList = new();
        foreach (var ctorParameter in ctor.GetParameters())
        {
            Type tageType = MapDic[ctorParameter.ParameterType.FullName];
            object oPrarmeter = CreateInstance(tageType);
            parametList.Add(oPrarmeter);
        }
        return Activator.CreateInstance(type, parametList.ToArray());
    }
}
[AttributeUsage(AttributeTargets.Constructor)]
public class SelectCtorAttribute : Attribute
{
}

调用:

IMyServiceCollection myServices = new MyServiceCollection();
myServices.Register<IHeadphone, Headphone>();
myServices.Register<IMicrophone, Microphone>();
myServices.Register<IPower, Power>();
myServices.Register<IPhone, AndroidPhone>();

IHeadphone headphone1 = myServices.GetService<IHeadphone>();
IMicrophone microphone1 = myServices.GetService<IMicrophone>();
IPower power1 = myServices.GetService<IPower>();
IPhone iphone1 = myServices.GetService<IPhone>();
cpp IOC容器和依赖注入 在复杂项目中,服务 A 可能依赖服务 B,而服务 B 又依赖服务 C。这种关系称为依赖链。IOC 容器需要递归解析依赖,自动注入所需的服务。示例依赖链。 阅读详情

相关推荐

嵌入式下载故障排查:ST-LINK与GD32 Programmer典型问题解决

嵌入式固件烧录是MCU开发的关键环节,其本质依赖于调试器(如ST-LINK、GD-Link)与目标芯片间的协议通信、驱动加载及硬件接口协同。原理上,SWD/JTAG协议需在正确时序、电平与供电条件下完成设备枚举、ID读取与Flash编程;技术价值在于保障量产烧录稳定性与调试可重复性;典型应用场景涵盖STM32/GD32教学开发、工业控制板量产调试及Windows 11新系统适配。本文聚焦ST-LINK-V2在Keil MDK中的下载失败和GD32 All In One Programmer的DLL加载异常两

weixin_35006125的博客 153

ioc与依赖注入

IOC就是一个Spring特有的,用来装类对象的,就是我们用Spring框架时,不需要new对象了,不过我们需要让我们的Spring知道我们写了哪些配置和需要用什么,所以这时我们就要引用Spring的注解或者在配置xml文件上配置我们的类配置,就是在我们自己写的类上加上@Component、@Controller、@Service、@Repository等等这些让我们的Spring知道我们等下要调用有哪些类,让它先准备准备,等下我们需要用了,就getBean或者通过@Autowrite、@Resource来

weixin_71307869的博客 1596

海洋科学—物理海洋学 第五章 海洋环流

本章是基于《海洋科学导论》,但里面涉及到的重要的公式推导是专门拎出来推的,主要借鉴董昌明老师的《物理海洋学导论》,其中有一些多出来的推导,会在更新完整个物理海洋学之后重新拿出来一一讲解,最后开一个番外篇

qq_58518586的博客 1万+

IOC是什么,以及IOC的注入方式【Spring的IOC是什么,注入方法有哪几种】

IOC是spring的核心,是spring的核心,它不是一种技术,而是一种思想,所谓IOC ,对于spring框架来说,就是由spring来负责控制对象的生命周期和对象间的关系。所有的类都会在spring容器中登记,告诉spring这是一个类对象,在不适用spring框架之前,我们使用一个对象通常需要在使用他的类或者方法中通过new关键字去创建该对象,而在spring框架中我们再去使用一个对象的时候,便不需要在取new这个对象了,只需要将该对象交给spring容器进行管理,子啊需要使用的时候直接从sprin

Coastlise的博客 929

Win11用户文件夹中文名修改全攻略

本文详细介绍了Windows 11系统中修改中文用户文件夹名称的完整步骤。操作包含七个关键环节:前期数据备份、账户名称修改、管理员账户激活、用户文件夹重命名、注册表路径更新、收尾操作及注意事项。特别强调需要同步修改账户名、文件夹名和注册表关联路径,并建议操作前备份重要数据。文中还针对常见问题提供了解决方案,如软件报错时的符号链接创建方法。整个过程需谨慎操作,建议在管理员权限下逐步执行,修改完成后需验证系统及软件功能是否正常。

Qinti_mm的博客 3120

学习 考证 帆软 FCP-FineBI V6.0 考试经验

参加这个学习班,认识了新朋友,可能是我职业生涯中的一次重要体验,其实大家想想 IT 和 医生一样都是需要终身学习的。只是医生学习周期更长但是回报率也更高。大家觉的呢?

小 tom的博客 6223

Spring——IOC(依赖注入)的三种方式

Spring ioc依赖注入的三种方式

qq_39350797的博客 571

馈电网络设计:通过Smith圆图工具完成微带线到同轴探针的阻抗匹配

Smith圆图通过图形化阻抗变换路径,显著简化微带线到同轴探针的匹配设计。设计需结合理论计算(微带线阻抗公式、探针等效模型)、圆图操作(串联/并联元件移动规则)及仿真验证,最终实现宽带低反射匹配。

百态·数智思维 | 聚焦大数据、量化与未来AI 1106

IOC 配置,依赖注入的三种方式

IOC配置 依赖注入 IOC是思想方法,DI是具体实现

m0_59519985的博客 1112

【NTN 卫星通信】使用地面网络和卫星网络接入的终端应用场景

卫星接入有广覆盖的特点, 可以改善地面接入网覆盖或无线条件差的地区(例如多径干扰)的服务可用性。对于高速移动中需要实时业务的终端,如IMS语音/视频会议,可以通过地面接入和卫星接入同时实现与5G系统的双连接,在地面接入网不可用的情况下获得连续可靠的业务。

weixin_43603524的博客 2558

AutoCAD提示找不到acdb24.dll、AcGe24.dll、AcPal.dll、AcUt.dll怎么办?

在我们安装了AutoCAD 2023版本以后,打开CAD,可能会出现dll文件丢失的情况,如下所示:1、由于找不到acdb24.dll,无法继续执行代码。重新安装程序可能解决此问题。2、由于找不到AcGe24.dll,无法继续执行代码。重新安装程序可能解决此问题。3、由于找不到AcPal.dll,无法继续执行代码。重新安装程序可能解决此问题。4、由于找不到AcUt.dll,无法继续执行代码。重新安装程序可能解决此问题。遇到AutoCAD启动系统错误,由于找不到dll文件该怎么处理呢?

huoxu369的博客 1万+

Spring--IOC和依赖注入

学习Spring

qq_45688655的博客 568

Python 爬虫实战:豆瓣 / IMDB 电影数据抓取(评分 + 剧情 + 演员阵容结构化处理)

在数据为王的时代,电影数据是进行市场分析、推荐系统构建和学术研究的重要资源。豆瓣和 IMDB 作为国内外最具影响力的电影评分和资讯网站,包含了海量高质量的电影数据。本文将带领你从零开始,构建一个健壮的 Python 爬虫,用于抓取豆瓣和 IMDB 的电影信息,并将其中的非结构化数据(如剧情简介、演员列表)进行清洗和结构化处理,最终存储到便于分析的结构化文件(如 CSV)中。

yansideyucsdn的博客 953

C#中的依赖注入和IoC容器

目录 介绍 要求 第一次尝试 第二次尝试 最终尝试 IoC容器 下载源代码7.9 KB 介绍 依赖注入和IoC乍一看似乎很复杂,但是它们很容易学习和理解。 在本文中,我们将通过在C#中重构一个非常简单的代码示例来说明依赖注入和IoC容器。 要求 构建一个允许用户查看可用产品并按名称搜索产品的应用程序。 第一次尝试 我们将从创建分层架构开始。使用分层体系结构有多种好处,但是由于我们专注于依赖注入,因此我们将不在本文中列出它们。 下面是该应用程序的类图: 首先,我们将从创建

寒冰屋的专栏 3240

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

详解C#中的依赖注入和IoC容器

在本文中,我们将通过用C#重构一个非常简单的代码示例来解释依赖注入和IoC容器。 简介: 依赖注入和IoC乍一看可能相当复杂,但它们非常容易学习和理解。 在本文中,我们将通过在C#中重构一个非常简单的代码示例来解释依赖注入和IoC容器。 要求: 构建一个允许用户查看可用产品并按名称搜索产品的应用程序。 第一次尝试: 我们将从创建分层架构开始。使用分层架构有多个好处,但我们不会在本文中列出它们,因为我们关注的是依赖注入。 下面是应用程序的类图: 首先,我们将从创建一个Product类开始: public

chinaherolts2008的博客 5994

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

PHP 依赖注入,简易 IOC 容器

什么是依赖注入如何依赖注入。 IOC 容器。依赖注入是什么,能干什么。

请叫我菜鸟 1249

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Spring Ioc容器依赖注入

Spring Ioc容器依赖注入

flykinghg的博客 1万+

看完后你就知道什么是依赖注入与Ioc容器了

在很多编程语言(例如java)开发中,程序员在某个类中需要依赖其它类的方法,则通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理,一旦有修改,牵扯的类会很多。 最早在java的spring提出了依赖注入的思想,即依赖类不由程序员实例化,而是通过spring容器帮我们new指定实例并且将实例注入到需要该对象的类中。目前许多主流PHP框架也使用了依赖注入容器,如...

Quan的博客 860

IOC容器的依赖注入

本节来学习IOC容器的依赖注入假设IOC容器已经载入了用户定义的Bean信息,开始分析依赖注入的原理。首先,依赖注入的过程是用户第一次向IOC容器索要Bean时触发的,当然也可以在BeanDefinition信息中通过控制lazy-init属性来让容器完成对Bean的预实例化。下面从DefaultListableBeanFactory的基类AbstractBeanFactory入手看一下getBe...

dxh0823的专栏 255

Java学习手册: IoC 容器与依赖注入

IoC(Inversion of Control,控制反转)容器是 Spring 框架的核心组件之一。它负责创建对象、管理对象的生命周期以及对象之间的依赖关系。通过将对象的创建和管理交给 IoC 容器,开发者可以实现代码的松耦合,提高代码的可测试性和可维护性。在 XML 配置文件中,使用<bean>标签来定义 Bean。在注解配置中,使用@Component@Service等注解来标记类为 Spring 管理的 Bean。XML 配置示例</注解配置示例@Component// 类内容。

佩奇的技术笔记 1217

依赖注入与Ioc容器

文章内容 背景 在很多编程语言(例如java)开发中,程序员在某个类中需要依赖其它类的方法,则通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理,一旦有修改,牵扯的类会很多。 最早在java的spring提出了依赖注入的思想,即依赖类不由程序员实例化,而是通过spring容器帮我们new指定实例并且将实例注入到需要该对象的类中。目前许多主流PHP框架也使用了依赖注入容器,如ThinkPHP、Laravel等。 一、概念 1、容器:字面上理解就是装东西的东西。常见的变量、

weixin_41882200的博客 324

【Spring】Ioc容器的依赖注入

1

蓝天之枫 649

什么是依赖注入与Ioc容器了

背景 在很多编程语言(例如java)开发中,程序员在某个类中需要依赖其它类的方法,则通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理,一旦有修改,牵扯的类会很多。 最早在java的spring提出了依赖注入的思想,即依赖类不由程序员实例化,而是通过spring容器帮我们new指定实例并且将实例注入到需要该对象的类中。目前许多主流PHP框架也使用了依赖注入...

谢谢你,慌乱了我的年华 609

什么是依赖注入与Ioc容器

背景 在很多编程语言(例如java)开发中,程序员在某个类中需要依赖其它类的方法,则通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理,一旦有修改,牵扯的类会很多。 最早在java的spring提出了依赖注入的思想,即依赖类不由程序员实例化,而是通过spring容器帮我们new指定实例并且将实例注入到需要该对象的类中。目前许多主流PHP框架也使用了依赖注入容器...

liuqun of program life 1135

Ioc容器的依赖注入-上篇

主要就是介绍了getBean()以及doGetBean()方法 我们已经从ioc容器的系列表中可以了解到:BeanDefinition数据的载入以及分析,以及注册等等,以及从前面来说标志一个Ioc容器完成初始化的事情就是BeanDefinition的注册事件,其实在Ioc容器完成初始化的一整个过程中,都只是完成BeanDefinition的数据映射功能呢,并没有将Bean的依赖关系注入Ioc容...

a_liuren的博客 257
上一篇: ASP.NET Core Blazor 5:Blazor表单和数据
下一篇: RabbitMQ-基本使用
似水明俊德
博客等级 码龄8年 247粉丝 276原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值