手机版

PHP高级学习中依赖注入和Ioc容器的详细说明

时间:2021-08-22 来源:互联网 编辑:宝哥软件园 浏览:

本文说明了PHP依赖注入和Ioc容器。分享给大家参考,如下:

背景

在许多编程语言(如java)的开发中,程序员需要依赖某个类中其他类的方法,这通常是一种依赖类然后调用类实例的方法。这种开发的问题是new的类实例不容易统一管理,一旦修改,就会涉及到很多类。

依赖注入的思想最早是在java的spring中提出的,即依赖类不是程序员实例化的,而是spring容器帮助我们指定实例,并将实例注入到需要对象的类中。目前很多主流的PHP框架也使用依赖注入容器,比如ThinkPHP和Laravel。

一.概念

1.容器:字面意思,它是装东西的东西。公共变量和对象属性可以看作容器。容器能装什么取决于你对容器的定义。当然,我们现在谈论的是这样一个容器,它存储对象、对象的描述(类和接口)或回调(闭包),这些对象提供对象而不是文本和数值。通过这个容器,我们可以实现许多高级功能,其中“解耦”和“依赖注入”是最常提到的。

2.控制反转的反转

控制反转是从容器的角度来描述的,即容器控制应用,容器反向注入应用需要的外部资源。

3.依赖注入依赖注入

依赖注入是从应用的角度来描述的,可以注入依赖,即一个应用依赖于容器来创建和注入它所需要的外部资源。

注意:依赖注入和控制反转指的是同一件事,是一种设计模式。这种设计模式用于减少程序之间的耦合。在某种程度上,它们是从不同的角度描述的。

二、依赖注射的原理

一般来说,当类之间存在依赖关系时,我们称之为直接实例化。一旦出现多层依赖,这种方法就有很高的耦合度。当其中一个类需要修改时,依赖它的很多类都会被修改,所以代码会发生很大的变化。

下面是一个简单的A-B-C依赖关系的例子,说明如何使用依赖注入来解耦和提高开发效率。

依赖注入模式如下:

解析:

在常规写作中,一旦C类需要更改,或者B类的调用需要更改为D类,也需要考虑依赖自己的B类,即需要修改B类.

依赖注入的思想是以其为实例,反转类之间的控制关系,实现通过调用类A来控制后续的依赖关系,使类B可以随意改变需要依赖和实例化的类(类C或类D),达到解耦的目的。

三、常用的依赖注入方法:

1.施工法注入;2.设置属性注入;3.静态工厂法注入;

上面的例子使用了构造方法注入的方式,将对象作为参数传递给构造方法;同一个set属性注入是一个类似的方法,只是在设置类成员的属性时传递了object参数,这里就不举例了。

此外,还有一个静态工厂方法注入方法,类似于静态工厂方法。

我们知道静态工厂方法是通过一个类来管理几个需要实例化的相似类,这个类会定义一个方法来获取需要实例化的对象,需要实例化哪些对象取决于传入的对象名参数。

对于静态工厂注入,与一般静态工厂方法的区别在于传入的参数是一个实例化的对象。

?phpclass IoC { protected static $ registry=[];公共静态函数bind ($ name,可调用的$ resolver)//传入类名和类对象实例{ static :3360 $ registry[$ name]=$ resolver;} public static function make($ name)//static factory方法{ if(isset(static :3360 $ registry[$ name]){ $ resolver=static :3360 $ registry[$ name];返回$ resolver();//实例化}引发新异常('别名在国际奥委会注册中心不存在');}}综上所述,三种方法都传递实例化对象,但不同的是传递的位置分别是构造函数、set属性和静态工厂方法。

四.依赖注入容器(Ioc容器)

大多数时候,当使用依赖注入来分离组件时,不需要容器。当一个程序需要实例化太多的类或者依赖太多的时候,重复依赖注入的代码是很繁琐的,例如:

当出现上述关系时,依赖注入的代码会被混淆和重复,更有可能在调用一般方法时创建不必要的类,导致冗余。

此时,需要使用容器。使用依赖注入容器后的想法是,如果应用程序需要获取类A,它将从容器中获取类A。具体来说,容器创建C类,然后创建B类并注入C,然后创建A类并注入B类,应用程序调用A类方法,A类调用B类方法,然后做其他工作。简而言之,容器负责实例化、注入依赖和处理依赖。

对于实际开发中复杂多变的代码环境,我们无法完全知道当前类未来会扩展成什么样。因此,当添加新的依赖类时,我们需要实现通过容器实例化这个类的方法。因此,在实例化未知类时,探索类的内部结构和实例化的最好方法是使用反射。因此,反射是每个依赖类的容器管理的核心。我们可以通过示例了解容器的内部实现:

三个依赖类:文件testClass.php

?PHP//dependency:company-department-group class group { public function do某物(){ echo _ _ class _ _ }。' :'.hello ',' | ';} } class Department { private $ group;public function _ _ construct(Group $ Group){ $ this-Group=$ Group;} public function do someting(){ $ this-group-do someting();echo _ _ CLASS _ _。':'.hello ',' | ';} }类Company { private $ department公共函数_ _ construct(Department $ Department){ $ this-Department=$ Department;} public function do someting(){ $ this-department-do someting();echo _ _ CLASS _ _。':'.hello ',' | ';}}Ioc容器的内部实现:

?phpclass容器{ private $ s=array();public function __set($k,$ c){ $ this-s[$ k]=$ c;} public function _ _ get($ k){ return $ this-build($ this-s[$ k]);} /** * 自动绑定(自动布线)自动解析(自动解析)* * @param字符串$类名* @返回对象* @引发异常*/公共函数生成($className) { //如果是匿名函数(匿名函数),也叫闭包函数(闭包)if($ Closure的className实例){//执行闭包函数,并将结果返回$类名($ this);} /*通过反射获取类的内部结构,实例化类*/$ reflector=new ReflectionClass($类名);//检查类是否可实例化,排除抽象类摘要和对象接口接口if(!$ reflector-is stantiable()){ 0引发新异常('无法实例化此异常。');}/* * @ var ReflectionMethod $构造函数获取类的构造函数*/$ constructor=$ reflector-getConstructor();//若无构造函数,直接实例化并返回if(is _ null($ constructor)){ 0返回新的$ className} //取构造函数参数,通过反射参数数组返回参数列表$ parameters=$ constructor-GetParameters();//递归解析构造函数的参数$ dependencies=$ this-getDependencies($ parameters);//创建一个类的新实例,给出的参数将传递到类的构造函数返回$ reflector-NewInstanceArgs($ dependencies);} /** * @param数组$ parameters * @返回数组* @抛出异常*/公共函数getDependencies($ parameters){ $ dependencies=[];/* * @ var ReflectionParameter $ parameter */foreach($ parameters as $ parameter){/* * @ var ReflectionClass $ dependency */$ dependency=$ parameter-getClass();if (is_null($dependency)) { //是变量,有默认值则设置默认值$ dependencies[]=$ this-resolveNonClass($参数);} else { //是一个类,递归解析$ dependencies[]=$ this-build($ dependency-name);} }返回$ dependencies }/* * * @ param ReflectionParameter $ parameter * @返回混合* @抛出异常*/公共函数resolveNonClass($参数){ //有默认值则返回默认值if($ parameter-isDefaultValueAvailable()){ return $ parameter-getDefaultValue();}抛出新的异常('我不知道在这里做什么');} }需要一次./test类。PHP ';//开始测试,先测试已知依赖关系的情况$c=新容器();$ c-部门='部门;$ c-公司=职能($ c){ 0返回新公司($ c-部门);};//从容器中取得公司$公司=$ c-公司;$ company-做点什么();//输出:组:你好|部门:你好|公司:你好|//测试未知依赖关系,直接使用的方法$di=新容器();$ di-公司=“公司”;$ company=$ di-company;$ company-做点什么();//输出:组:你好|部门:你好|公司:你好|我们可以通过一张图解释国际奥委会容器的内部逻辑:

五、总结

国际奥林匹克委员会的基本概念是:不创建对象,但是描述创建它们的方式。在代码中不直接与对象和服务连接,但在配置文件中描述哪一个组件需要哪一项服务春天容器负责将这些联系在一起。也就是说春天,的国际奥林匹克委员会负责管理各种对象的创建、清除以及它们之间的联系。

更多关于服务器端编程语言(专业超文本预处理器的缩写)相关内容感兴趣的读者可查看本站专题: 《php面向对象程序设计入门教程》 、 《PHP数组(Array)操作技巧大全》 、 《PHP基本语法入门教程》 、 《PHP运算与运算符用法总结》 、 《php字符串(string)用法总结》 、 《php+mysql数据库操作入门教程》 及《php常见数据库操作技巧汇总》

希望本文所述对大家服务器端编程语言(专业超文本预处理器的缩写)程序设计有所帮助。

版权声明:PHP高级学习中依赖注入和Ioc容器的详细说明是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。