国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專(zhuān)欄INFORMATION COLUMN

淺析如何通過(guò)PHP類(lèi)的反射來(lái)實(shí)現(xiàn)依賴(lài)注入

WilsonLiu95 / 2108人閱讀

摘要:也正式因?yàn)轭?lèi)的反射很多框架才能實(shí)現(xiàn)依賴(lài)注入自動(dòng)解決類(lèi)與類(lèi)之間的依賴(lài)關(guān)系,這給我們平時(shí)的開(kāi)發(fā)帶來(lái)了很大的方便。為了更好地理解,我們通過(guò)一個(gè)例子來(lái)看類(lèi)的反射,以及如何實(shí)現(xiàn)依賴(lài)注入。反射出方法的參數(shù)其返回值為對(duì)象構(gòu)成的數(shù)組。

PHP具有完整的反射 API,提供了對(duì)類(lèi)、接口、函數(shù)、方法和擴(kuò)展進(jìn)行逆向工程的能力。通過(guò)類(lèi)的反射提供的能力我們能夠知道類(lèi)是如何被定義的,它有什么屬性、什么方法、方法都有哪些參數(shù),類(lèi)文件的路徑是什么等很重要的信息。也正式因?yàn)轭?lèi)的反射很多PHP框架才能實(shí)現(xiàn)依賴(lài)注入自動(dòng)解決類(lèi)與類(lèi)之間的依賴(lài)關(guān)系,這給我們平時(shí)的開(kāi)發(fā)帶來(lái)了很大的方便。 本文主要是講解如何利用類(lèi)的反射來(lái)實(shí)現(xiàn)依賴(lài)注入(Dependency Injection),并不會(huì)去逐條講述PHP Reflection里的每一個(gè)API,詳細(xì)的API參考信息請(qǐng)查閱官方文檔

再次聲明這里實(shí)現(xiàn)的依賴(lài)注入非常簡(jiǎn)單,并不能應(yīng)用到實(shí)際開(kāi)發(fā)中去,可以參考我的另一篇文章來(lái)了解laravel框架的服務(wù)容器(IocContainer), 在那里會(huì)介紹Laravel的服務(wù)容器是如何實(shí)現(xiàn)依賴(lài)注入的。

為了更好地理解,我們通過(guò)一個(gè)例子來(lái)看類(lèi)的反射,以及如何實(shí)現(xiàn)依賴(lài)注入。
下面這個(gè)類(lèi)代表了坐標(biāo)系里的一個(gè)點(diǎn),有兩個(gè)屬性橫坐標(biāo)x和縱坐標(biāo)y。

/**
 * Class Point
 */
class Point
{
    public $x;
    public $y;

    /**
     * Point constructor.
     * @param int $x  horizontal value of point"s coordinate
     * @param int $y  vertical value of point"s coordinate
     */
    public function __construct($x = 0, $y = 0)
    {
        $this->x = $x;
        $this->y = $y;
    }
}

接下來(lái)這個(gè)類(lèi)代表圓形,可以看到在它的構(gòu)造函數(shù)里有一個(gè)參數(shù)是Point類(lèi)的,即Circle類(lèi)是依賴(lài)與Point類(lèi)的。

class Circle
{
    /**
     * @var int
     */
    public $radius;//半徑

    /**
     * @var Point
     */
    public $center;//圓心點(diǎn)

    const PI = 3.14;

    public function __construct(Point $point, $radius = 1)
    {
        $this->center = $point;
        $this->radius = $radius;
    }
    
    //打印圓點(diǎn)的坐標(biāo)
    public function printCenter()
    {
        printf("center coordinate is (%d, %d)", $this->center->x, $this->center->y);
    }

    //計(jì)算圓形的面積
    public function area()
    {
        return 3.14 * pow($this->radius, 2);
    }
}
ReflectionClass

下面我們通過(guò)反射來(lái)對(duì)Circle這個(gè)類(lèi)進(jìn)行反向工程。
Circle類(lèi)的名字傳遞給reflectionClass來(lái)實(shí)例化一個(gè)ReflectionClass類(lèi)的對(duì)象。

$reflectionClass = new reflectionClass(Circle::class);
//返回值如下
object(ReflectionClass)#1 (1) {
  ["name"]=>
  string(6) "Circle"
}
反射出類(lèi)的常量
$reflectionClass->getConstants();

返回一個(gè)由常量名稱(chēng)和值構(gòu)成的關(guān)聯(lián)數(shù)組

array(1) {
  ["PI"]=>
  float(3.14)
}
通過(guò)反射獲取屬性
$reflectionClass->getProperties();

返回一個(gè)由ReflectionProperty對(duì)象構(gòu)成的數(shù)組

array(2) {
  [0]=>
  object(ReflectionProperty)#2 (2) {
    ["name"]=>
    string(6) "radius"
    ["class"]=>
    string(6) "Circle"
  }
  [1]=>
  object(ReflectionProperty)#3 (2) {
    ["name"]=>
    string(6) "center"
    ["class"]=>
    string(6) "Circle"
  }
}
反射出類(lèi)中定義的方法
$reflectionClass->getMethods();

返回ReflectionMethod對(duì)象構(gòu)成的數(shù)組

array(3) {
  [0]=>
  object(ReflectionMethod)#2 (2) {
    ["name"]=>
    string(11) "__construct"
    ["class"]=>
    string(6) "Circle"
  }
  [1]=>
  object(ReflectionMethod)#3 (2) {
    ["name"]=>
    string(11) "printCenter"
    ["class"]=>
    string(6) "Circle"
  }
  [2]=>
  object(ReflectionMethod)#4 (2) {
    ["name"]=>
    string(4) "area"
    ["class"]=>
    string(6) "Circle"
  }
}

我們還可以通過(guò)getConstructor()來(lái)多帶帶獲取類(lèi)的構(gòu)造方法,其返回值為一個(gè)ReflectionMethod對(duì)象。

$constructor = $reflectionClass->getConstructor();
反射出方法的參數(shù)
$parameters = $constructor->getParameters();

其返回值為ReflectionParameter對(duì)象構(gòu)成的數(shù)組。

array(2) {
  [0]=>
  object(ReflectionParameter)#3 (1) {
    ["name"]=>
    string(5) "point"
  }
  [1]=>
  object(ReflectionParameter)#4 (1) {
    ["name"]=>
    string(6) "radius"
  }
}
依賴(lài)注入

好了接下來(lái)我們編寫(xiě)一個(gè)名為make的函數(shù),傳遞類(lèi)名稱(chēng)給make函數(shù)返回類(lèi)的對(duì)象,在make里它會(huì)幫我們注入類(lèi)的依賴(lài),即在本例中幫我們注入Point對(duì)象給Circle類(lèi)的構(gòu)造方法。

//構(gòu)建類(lèi)的對(duì)象
function make($className)
{
    $reflectionClass = new ReflectionClass($className);
    $constructor = $reflectionClass->getConstructor();
    $parameters  = $constructor->getParameters();
    $dependencies = getDependencies($parameters);
    
    return $reflectionClass->newInstanceArgs($dependencies);
}

//依賴(lài)解析
function getDependencies($parameters)
{
    $dependencies = [];
    foreach($parameters as $parameter) {
        $dependency = $parameter->getClass();
        if (is_null($dependency)) {
            if($parameter->isDefaultValueAvailable()) {
                $dependencies[] = $parameter->getDefaultValue();
            } else {
                //不是可選參數(shù)的為了簡(jiǎn)單直接賦值為字符串0
                //針對(duì)構(gòu)造方法的必須參數(shù)這個(gè)情況
                //laravel是通過(guò)service provider注冊(cè)closure到IocContainer,
                //在closure里可以通過(guò)return new Class($param1, $param2)來(lái)返回類(lèi)的實(shí)例
                //然后在make時(shí)回調(diào)這個(gè)closure即可解析出對(duì)象
                //具體細(xì)節(jié)我會(huì)在另一篇文章里面描述
                $dependencies[] = "0";
            }
        } else {
            //遞歸解析出依賴(lài)類(lèi)的對(duì)象
            $dependencies[] = make($parameter->getClass()->name);
        }
    }

    return $dependencies;
}

定義好make方法后我們通過(guò)它來(lái)幫我們實(shí)例化Circle類(lèi)的對(duì)象:

$circle = make("Circle");
$area = $circle->area();
/*var_dump($circle, $area);
object(Circle)#6 (2) {
  ["radius"]=>
  int(1)
  ["center"]=>
  object(Point)#11 (2) {
    ["x"]=>
    int(0)
    ["y"]=>
    int(0)
  }
}
float(3.14)*/

通過(guò)上面這個(gè)實(shí)例我簡(jiǎn)單描述了一下如何利用PHP類(lèi)的反射來(lái)實(shí)現(xiàn)依賴(lài)注入,Laravel的依賴(lài)注入也是通過(guò)這個(gè)思路來(lái)實(shí)現(xiàn)的,只不過(guò)設(shè)計(jì)的更精密大量地利用了閉包回調(diào)來(lái)應(yīng)對(duì)各種復(fù)雜的依賴(lài)注入,詳情可以參考我的另一篇介紹Laravel服務(wù)容器的文章。

本文的示例代碼的下載鏈接

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/26282.html

相關(guān)文章

  • 搞懂依賴(lài)注入, 用 PHP 手寫(xiě)簡(jiǎn)易 IOC 容器

    摘要:依賴(lài)注入控制反轉(zhuǎn)的一種具體實(shí)現(xiàn)方法。接下來(lái),我們使用依賴(lài)注入實(shí)現(xiàn)控制反轉(zhuǎn),使依賴(lài)關(guān)系倒置依賴(lài)被動(dòng)傳入。從單元測(cè)試的角度看,依賴(lài)注入更方便和操作,方便了測(cè)試人員寫(xiě)出質(zhì)量更高的測(cè)試代碼。 前言 好的設(shè)計(jì)會(huì)提高程序的可復(fù)用性和可維護(hù)性,也間接的提高了開(kāi)發(fā)人員的生產(chǎn)力。今天,我們就來(lái)說(shuō)一下在很多框架中都使用的依賴(lài)注入。 一些概念 要搞清楚什么是依賴(lài)注入如何依賴(lài)注入,首先我們要明確一些概念。 D...

    antz 評(píng)論0 收藏0
  • Laravel深入學(xué)習(xí)2 - 控制反轉(zhuǎn)容器

    摘要:控制反轉(zhuǎn)容器控制反轉(zhuǎn)使依賴(lài)注入變得更加便捷。有瑕疵控制反轉(zhuǎn)容器是實(shí)現(xiàn)的控制翻轉(zhuǎn)容器的一種替代方案。容器的獨(dú)立使用即使沒(méi)有使用框架,我們?nèi)匀豢梢栽陧?xiàng)目中使用安裝組件來(lái)使用的控制反轉(zhuǎn)容器。在沒(méi)有給定任何信息的情況下,容器是無(wú)法實(shí)例化相關(guān)依賴(lài)的。 聲明:本文并非博主原創(chuàng),而是來(lái)自對(duì)《Laravel 4 From Apprentice to Artisan》閱讀的翻譯和理解,當(dāng)然也不是原汁原味...

    worldligang 評(píng)論0 收藏0
  • PHP程序員如何理解依賴(lài)注入容器(dependency injection container)

    摘要:代碼這就是控制反轉(zhuǎn)模式。是變量有默認(rèn)值則設(shè)置默認(rèn)值是一個(gè)類(lèi),遞歸解析有默認(rèn)值則返回默認(rèn)值從容器中取得以上代碼的原理參考官方文檔反射,具有完整的反射,添加了對(duì)類(lèi)接口函數(shù)方法和擴(kuò)展進(jìn)行反向工程的能力。 PHP程序員如何理解依賴(lài)注入容器(dependency injection container) 背景知識(shí) 傳統(tǒng)的思路是應(yīng)用程序用到一個(gè)Foo類(lèi),就會(huì)創(chuàng)建Foo類(lèi)并調(diào)用Foo類(lèi)的方法,假如這...

    Coding01 評(píng)論0 收藏0
  • Java深入-框架技巧

    摘要:從使用到原理學(xué)習(xí)線程池關(guān)于線程池的使用,及原理分析分析角度新穎面向切面編程的基本用法基于注解的實(shí)現(xiàn)在軟件開(kāi)發(fā)中,分散于應(yīng)用中多出的功能被稱(chēng)為橫切關(guān)注點(diǎn)如事務(wù)安全緩存等。 Java 程序媛手把手教你設(shè)計(jì)模式中的撩妹神技 -- 上篇 遇一人白首,擇一城終老,是多么美好的人生境界,她和他歷經(jīng)風(fēng)雨慢慢變老,回首走過(guò)的點(diǎn)點(diǎn)滴滴,依然清楚的記得當(dāng)初愛(ài)情萌芽的模樣…… Java 進(jìn)階面試問(wèn)題列表 -...

    chengtao1633 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<