>  기사  >  백엔드 개발  >  PHP 반사 메커니즘은 자동 종속성 주입을 실현합니다.

PHP 반사 메커니즘은 자동 종속성 주입을 실현합니다.

不言
不言원래의
2018-04-18 09:11:471398검색

이 기사에서는 자동 종속성 주입을 달성하기 위한 PHP 반사 메커니즘을 소개합니다. 이제 모든 사람과 공유합니다. 필요한 친구가 참조할 수 있습니다.

종속성 주입을 제어 역전이라고도 합니다. 프레임워크 모두가 그것에 익숙해야 합니다. 많은 사람들이 이름을 보고 매우 고급스러운 제품이라고 생각하고 겁을 먹습니다. 오늘은 시간을 내어 조사를 하고 그 미스터리를 풀어봤습니다. 더 이상 고민하지 않고 바로 코드로 넘어가겠습니다.

/**
*
* 工具类,使用该类来实现自动依赖注入。
*
*/class Ioc {

    // 获得类的对象实例
    public static function getInstance($className) {

        $paramArr = self::getMethodParams($className);        return (new ReflectionClass($className))->newInstanceArgs($paramArr);
    }    /**
     * 执行类的方法
     * @param  [type] $className  [类名]
     * @param  [type] $methodName [方法名称]
     * @param  [type] $params     [额外的参数]
     * @return [type]             [description]
     */
    public static function make($className, $methodName, $params = []) {

        // 获取类的实例
        $instance = self::getInstance($className);        // 获取该方法所需要依赖注入的参数
        $paramArr = self::getMethodParams($className, $methodName);        return $instance->{$methodName}(...array_merge($paramArr, $params));
    }    /**
     * 获得类的方法参数,只获得有类型的参数
     * @param  [type] $className   [description]
     * @param  [type] $methodsName [description]
     * @return [type]              [description]
     */
    protected static function getMethodParams($className, $methodsName = '__construct') {

        // 通过反射获得该类
        $class = new ReflectionClass($className);        $paramArr = []; // 记录参数,和参数类型

        // 判断该类是否有构造函数
        if ($class->hasMethod($methodsName)) {            // 获得构造函数
            $construct = $class->getMethod($methodsName);            // 判断构造函数是否有参数
            $params = $construct->getParameters();            if (count($params) > 0) {                // 判断参数类型
                foreach ($params as $key => $param) {                    if ($paramClass = $param->getClass()) {                        // 获得参数类型名称
                        $paramClassName = $paramClass->getName();                        // 获得参数类型
                        $args = self::getMethodParams($paramClassName);                        $paramArr[] = (new ReflectionClass($paramClass->getName()))->newInstanceArgs($args);
                    }
                }
            }
        }        return $paramArr;
    }
}

위 코드는 PHP의 리플렉션 함수를 사용하여 컨테이너 클래스를 생성하고 이 클래스를 사용하여 다른 클래스의 종속성 주입 기능을 구현합니다. 위의 의존성 주입은 생성자의 의존성 주입과 메소드의 의존성 주입 두 가지로 나누어진다. 테스트를 위해 다음 세 가지 클래스를 사용합니다.

class A {    protected $cObj;    /**
     * 用于测试多级依赖注入 B依赖A,A依赖C
     * @param C $c [description]
     */
    public function __construct(C $c) {

        $this->cObj = $c;
    }    public function aa() {

        echo 'this is A->test';
    }    public function aac() {

        $this->cObj->cc();
    }
}

class B {    protected $aObj;    /**
     * 测试构造函数依赖注入
     * @param A $a [使用引来注入A]
     */
    public function __construct(A $a) {

        $this->aObj = $a;
    }    /**
     * [测试方法调用依赖注入]
     * @param  C      $c [依赖注入C]
     * @param  string $b [这个是自己手动填写的参数]
     * @return [type]    [description]
     */
    public function bb(C $c, $b) {

        $c->cc();
        echo "\r\n";

        echo 'params:' . $b;
    }    /**
     * 验证依赖注入是否成功
     * @return [type] [description]
     */
    public function bbb() {

        $this->aObj->aac();
    }
}

class C {    public function cc() {

        echo 'this is C->cc';
    }
}
  1. 생성자의 테스트 종속성 주입

// 使用Ioc来创建B类的实例,B的构造函数依赖A类,A的构造函数依赖C类。$bObj = Ioc::getInstance('B');
$bObj->bbb(); // 输出:this is C->cc , 说明依赖注入成功。// 打印$bObjvar_dump($bObj);// 打印结果,可以看出B中有A实例,A中有C实例,说明依赖注入成功。object(B)#3 (1) {
  ["aObj":protected]=>  object(A)#7 (1) {
    ["cObj":protected]=>    object(C)#10 (0) {
    }
  }
}
  1. 테스트 메서드 종속성 주입

Ioc::make('B', 'bb', ['this is param b']);// 输出结果,可以看出依赖注入成功。this is C->ccparams:this is param b

위의 두 가지 예를 보면 객체를 생성하거나 메서드를 호출할 때, 이 클래스나 메서드가 어떤 클래스에 의존하는지 알 필요가 없습니다. 리플렉션 메커니즘을 사용하면 필요한 클래스를 쉽게 자동으로 주입할 수 있습니다.

요약

알겠습니다. 위 코드가 매우 간단하다고 생각하시나요? 사실, PHP의 리플렉션 메커니즘에 익숙하다면 종속성 주입은 간단하게 작성되어 있습니다. 실제 프로젝트에서는 주입된 클래스와 매개변수가 구성되므로 다음에 클래스 인스턴스가 필요할 때 캐시됩니다. 다시 초기화하지 않고 직접 사용할 수 있습니다. 하지만 일단 원칙을 이해하면 프로젝트의 필요에 따라 나머지 부분을 개선할 수 있다고 믿습니다.

관련 추천:

PHP 리플렉션의 실제 적용 예 공유

실행 클래스에서 프라이빗 메서드를 호출하는 PHP 리플렉션 메서드에 대한 자세한 설명

위 내용은 PHP 반사 메커니즘은 자동 종속성 주입을 실현합니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.