亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 語言 > PHP > 正文

PHP進階學習之依賴注入與Ioc容器詳解

2024-05-05 00:09:44
字體:
來源:轉載
供稿:網友

本文實例講述了PHP依賴注入與Ioc容器。分享給大家供大家參考,具體如下:

背景

在很多編程語言(例如java)開發中,程序員在某個類中需要依賴其它類的方法,則通常是new一個依賴類再調用類實例的方法,這種開發存在的問題是new的類實例不好統一管理,一旦有修改,牽扯的類會很多。

最早在java的spring提出了依賴注入的思想,即依賴類不由程序員實例化,而是通過spring容器幫我們new指定實例并且將實例注入到需要該對象的類中。目前許多主流PHP框架也使用了依賴注入容器,如ThinkPHP、Laravel等。

一、概念

1、容器:字面上理解就是裝東西的東西。常見的變量、對象屬性等都可以算是容器。一個容器能夠裝什么,全部取決于你對該容器的定義。當然,現在我們討論的是這樣一種容器,它存放的不是文本、數值,而是對象、對象的描述(類、接口)或者是提供對象的回調(閉包),通過這種容器,我們得以實現許多高級的功能,其中最常提到的,就是 “解耦”、“依賴注入”。

2、IoC - Inversion of Control 控制反轉 

控制反轉是從容器的角度在描述,即:容器控制應用程序,由容器反向的向應用程序注入應用程序所需要的外部資源。 

3、DI - Dependency Injection 依賴注入 

依賴注入是從應用程序的角度在描述,可以把依賴注入,即:應用程序依賴容器創建并注入它所需要的外部資源。

備注:依賴注入和控制反轉說的是同一個東西,是一種設計模式,這種設計模式用來減少程序間的耦合,從某個方面講,就是它們描述的角度不同。 

二、依賴注入的原理

一般情況下,當存在類與類之間的依賴關系的時候,我們都是通過直接實例化的方式進行調用。一旦出現多層依賴,這種方式的耦合程度就很高,在需要修改其中一個類的時候,會牽扯很多依賴它的類的修改,因此對代碼的改動會比較大。

下面簡單舉一個A->B->C三層依賴的關系解釋怎么運用依賴注入來解耦,提高開發效率。

PHP,依賴注入,Ioc容器

而依賴注入方式如下:

PHP,依賴注入,Ioc容器

解析:

常規寫法里面,一旦C類需要作出改變,或者B類的調用需要改變成D類的時候,還需要考慮到依賴自己的B類,即還需要對B類作出修改。

依賴注入的思想就是即用即實例,反轉類與類之間的控制關系,實現由調用類A類控制后續的依賴關系,這樣可以讓B類隨意的更改所需依賴和實例化的類(C類或D類),達到解耦的目的。

PHP,依賴注入,Ioc容器

三、常用的依賴注入方式:

1、構造方法注入;2、set屬性注入;3、靜態工廠方法注入;

上述的例子使用的就是構造方法注入的方式,將對象作為參數傳遞到構造方法中;同樣的set屬性注入也是相類似的方法,不同的僅僅是在set一個類的成員的屬性時傳遞這個對象參數,在此就不一一舉例了。

除此之外,還有靜態工廠方法注入的方式,這種方法與靜態工廠方法類似。

我們知道靜態工廠方法就是通過一個類來管理需要實例化的多個相似的類,該類會定義一個方法用于獲取需要實例化的對象,而具體要實例化哪個對象就依賴于傳遞進來的對象名參數了。

對于靜態工廠方式的注入,與一般的靜態工廠方法不同之處在于這個傳進來的參數是一個已經實例化過的對象。

<?phpclass IoC{  protected static $registry = [];  public static function bind($name, Callable $resolver) //傳入類名和類對象實例  {    static::$registry[$name] = $resolver;  }  public static function make($name) //靜態工廠方法  {    if (isset(static::$registry[$name])) {      $resolver = static::$registry[$name];      return $resolver(); //實例化    }    throw new Exception('Alias does not exist in the IoC registry.');  }}

總而言之,三種方式傳遞的都是實例化對象,只是不同之處在于傳遞的位置分別為構造方法、set屬性、靜態工廠方法而已。

四、依賴注入容器(Ioc容器)

大多數時侯,在使用依賴注入方式解耦組件時,并不需要用到容器。
當一段程序需要實例化的類太多或者依賴太多的時候,重復依賴注入的代碼是比較繁瑣的事情,例如以下情況:

PHP,依賴注入,Ioc容器

當產生以上關系的時候,依賴注入的代碼會比較混亂,而且存在重復,更有可能在調用一個一般方法時new一個不需要的類,產生冗余。

此時需要使用容器,使用依賴注入容器后的思路是應用程序需要到A類,就從容器內取得A類。具體是容器創建C類,再創建B類并把C注入,再創建A類,并把B類注入,應用程序調用A類方法, A類調用B類方法,接著做些其它工作.總之容器負責實例化,注入依賴,處理依賴關系等工作。

PHP,依賴注入,Ioc容器

PHP,依賴注入,Ioc容器

對于實際開發中復雜多變的代碼環境,我們并不能完全知道現在的類在未來會擴展成什么情況,因此我們需要在有新的依賴類加入的時候,通過容器去實現實例化該類的方法。因此,在實例化未知類的時候,最能探索一個類的內部結構和實例化的方法就是利用反射,由此可知,反射是容器管理各個依賴類的核心。我們可以通過實例來了解容器的內部實現:

三個存在依賴關系的類:文件testClass.php

<?php //依賴關系:Company->Department->Groupclass Group{  public function doSomething()  {    echo __CLASS__.":".'hello', '|';  }}class Department{  private $group;  public function __construct(Group $group)  {    $this->group = $group;  }  public function doSomething()  {    $this->group->doSomething();    echo __CLASS__.":".'hello', '|';  }}class Company{  private $department;  public function __construct(Department $department)  {    $this->department = $department;  }  public function doSomething()  {    $this->department->doSomething();    echo __CLASS__.":".'hello', '|';  }}

Ioc容器的內部實現:

<?phpclass Container{  private $s = array();  public function __set($k, $c)  {    $this->s[$k] = $c;  }  public function __get($k)  {    return $this->build($this->s[$k]);  }  /**   * 自動綁定(Autowiring)自動解析(Automatic Resolution)   *   * @param string $className   * @return object   * @throws Exception   */  public function build($className)  {    // 如果是匿名函數(Anonymous functions),也叫閉包函數(closures)    if ($className instanceof Closure) {      // 執行閉包函數,并將結果      return $className($this);    }    /*通過反射獲取類的內部結構,實例化類*/    $reflector = new ReflectionClass($className);    // 檢查類是否可實例化, 排除抽象類abstract和對象接口interface    if (!$reflector->isInstantiable()) {      throw new Exception("Can't instantiate this.");    }    /** @var ReflectionMethod $constructor 獲取類的構造函數 */    $constructor = $reflector->getConstructor();    // 若無構造函數,直接實例化并返回    if (is_null($constructor)) {      return new $className;    }    // 取構造函數參數,通過 ReflectionParameter 數組返回參數列表    $parameters = $constructor->getParameters();    // 遞歸解析構造函數的參數    $dependencies = $this->getDependencies($parameters);    // 創建一個類的新實例,給出的參數將傳遞到類的構造函數。    return $reflector->newInstanceArgs($dependencies);  }  /**   * @param array $parameters   * @return array   * @throws Exception   */  public function getDependencies($parameters)  {    $dependencies = [];    /** @var ReflectionParameter $parameter */    foreach ($parameters as $parameter) {      /** @var ReflectionClass $dependency */      $dependency = $parameter->getClass();      if (is_null($dependency)) {        // 是變量,有默認值則設置默認值        $dependencies[] = $this->resolveNonClass($parameter);      } else {        // 是一個類,遞歸解析        $dependencies[] = $this->build($dependency->name);      }    }    return $dependencies;  }  /**   * @param ReflectionParameter $parameter   * @return mixed   * @throws Exception   */  public function resolveNonClass($parameter)  {    // 有默認值則返回默認值    if ($parameter->isDefaultValueAvailable()) {      return $parameter->getDefaultValue();    }    throw new Exception('I have no idea what to do here.');  }}require_once "./testclass.php"; //開始測試,先測試已知依賴關系的情況$c = new Container();$c->department = 'Department';$c->company = function ($c) {  return new Company($c->department);};// 從容器中取得company$company = $c->company;$company->doSomething(); //輸出: Group:hello|Department:hello|Company:hello|// 測試未知依賴關系,直接使用的方法$di = new Container();$di->company = 'Company';$company = $di->company;$company->doSomething();//輸出: Group:hello|Department:hello|Company:hello|

我們可以通過一張圖解釋Ioc容器的內部邏輯:

PHP,依賴注入,Ioc容器

五、總結

IOC的基本概念是:不創建對象,但是描述創建它們的方式。在代碼中不直接與對象和服務連接,但在配置文件中描述哪一個組件需要哪一項服務。Spring容器負責將這些聯系在一起。也就是說,Spring的IOC負責管理各種對象的創建、清除以及它們之間的聯系。 

希望本文所述對大家PHP程序設計有所幫助。


注:相關教程知識閱讀請移步到PHP教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲bt欧美bt日本bt| 久久成人在线视频| 91免费高清视频| 懂色av影视一区二区三区| 亚洲第一男人av| 青青久久av北条麻妃海外网| 国产视频自拍一区| 亚洲日韩中文字幕在线播放| 日韩性生活视频| 国产精品69精品一区二区三区| 欧美高清视频在线| 日韩中文字幕免费视频| 高潮白浆女日韩av免费看| 亚洲视频在线免费看| 美女久久久久久久久久久| 久久免费国产视频| 一区二区三区久久精品| 日本不卡视频在线播放| 亚洲福利视频在线| 日韩精品极品毛片系列视频| 91av在线播放| 国产精品扒开腿做| 亚洲欧洲一区二区三区在线观看| 日韩av在线免费观看一区| 97人人做人人爱| 成人在线精品视频| 欧美电影在线观看| 91美女福利视频高清| 欧美激情va永久在线播放| 色一区av在线| 欧美激情精品久久久久| 成人天堂噜噜噜| 操日韩av在线电影| 国产精品高清免费在线观看| 成人综合网网址| 亚洲欧美日韩图片| 91干在线观看| www.99久久热国产日韩欧美.com| 91av在线播放| 久久久久久网站| 国产最新精品视频| 欧美黑人xxx| 国产精品久久久久久久久久99| 这里只有视频精品| 国产69精品久久久久久| 久久精品国产久精国产一老狼| 国产精品成人一区二区三区吃奶| 91美女福利视频高清| 中文国产成人精品久久一| 精品美女永久免费视频| 国产精品美女午夜av| 欧美一区二区.| 日韩av中文字幕在线免费观看| 一区二区欧美在线| 91精品视频在线看| 亚洲第一综合天堂另类专| 欧美裸身视频免费观看| 国产精品三级在线| 国产成人福利夜色影视| 国产乱人伦真实精品视频| 亚洲一区免费网站| 亚洲天堂免费观看| 一道本无吗dⅴd在线播放一区| 日韩免费观看av| 91久久久久久久一区二区| 精品伊人久久97| 91天堂在线观看| 日本成人激情视频| 国产精品视频精品| 青青a在线精品免费观看| 一区二区三区视频在线| 欧美www视频在线观看| 亚洲热线99精品视频| 欧美精品成人91久久久久久久| 久久久久国产精品一区| 日韩中文字幕在线看| 日韩欧美精品在线观看| 日韩欧美视频一区二区三区| 欧美亚洲另类激情另类| 国产成人精品久久二区二区| 久久九九亚洲综合| 懂色av中文一区二区三区天美| 操日韩av在线电影| 亚洲精品在线视频| 一本色道久久综合狠狠躁篇的优点| 国产亚洲激情在线| 亚洲国产精品人久久电影| 91社区国产高清| 久久精品国产69国产精品亚洲| 亚洲乱码av中文一区二区| 国内精品国产三级国产在线专| 成人乱人伦精品视频在线观看| 精品视频在线观看日韩| 操日韩av在线电影| 国产精品成人av在线| 亚洲美女av在线| 日本午夜精品理论片a级appf发布| 正在播放欧美视频| 国产精品96久久久久久又黄又硬| 在线成人激情视频| 精品国内亚洲在观看18黄| 日韩网站免费观看| 欧美激情视频一区| 亚洲国产另类 国产精品国产免费| 亚洲精品久久久久久久久久久久| 日韩成人激情在线| 国产精品爱啪在线线免费观看| 亚洲人成欧美中文字幕| 日韩av第一页| www.欧美精品一二三区| 亚洲qvod图片区电影| 精品久久中文字幕久久av| 俺也去精品视频在线观看| 在线成人中文字幕| 成人动漫网站在线观看| 在线观看欧美日韩国产| 亚洲精品欧美日韩| 国产精品欧美久久久| 91精品国产91久久久久久久久| 久久国产精品电影| 国产精品免费久久久| 欧美中文在线字幕| 色无极影院亚洲| 午夜精品久久久久久久白皮肤| 国产亚洲精品成人av久久ww| 中文字幕日韩精品在线| 国产亚洲欧美日韩一区二区| 日韩电影免费在线观看| 亚洲精品日韩在线| 青青久久aⅴ北条麻妃| 国产不卡精品视男人的天堂| 国产丝袜一区视频在线观看| 精品国产网站地址| 国产午夜精品全部视频播放| 日韩欧美精品网站| 狠狠躁夜夜躁久久躁别揉| 91国偷自产一区二区三区的观看方式| 亚洲男人天堂九九视频| 久久久久国产精品免费网站| 欧美视频中文字幕在线| 亚洲影院在线看| 欧美精品在线免费播放| 国产视频精品一区二区三区| 97国产suv精品一区二区62| 亚洲午夜未满十八勿入免费观看全集| 欧美美女18p| 国产精品免费观看在线| 欧美巨大黑人极品精男| 精品国产拍在线观看| 久久精品中文字幕一区| 国产www精品| 亚洲xxx视频| 欧美性猛交xxxx富婆| 国产精品电影网站| 久久精品国产电影| 欧美黑人巨大xxx极品| 一二美女精品欧洲| 亚洲精品在线91| 2019中文字幕免费视频| 国产视频福利一区| 国产视频综合在线| 黑人精品xxx一区一二区| 色噜噜狠狠狠综合曰曰曰| 欧美wwwwww|