PHP의 리플렉션 메커니즘을 이용한 자동 종속성 주입에 대한 자세한 설명

韦小宝
풀어 주다: 2023-03-21 11:38:01
원래의
1765명이 탐색했습니다.

이 글에서는 PHP가 반사 메커니즘과 자동으로 종속성 주입을 구현하는 방법을 설명합니다. 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 , 说明依赖注入成功。

// 打印$bObj
var_dump($bObj);

// 打印结果,可以看出B中有A实例,A中有C实例,说明依赖注入成功。
object(B)#3 (1) {
  ["aObj":protected]=>
  object(A)#7 (1) {
    ["cObj":protected]=>
    object(C)#10 (0) {
    }
  }
}
로그인 후 복사

2. 테스트 메서드의 종속성 주입

Ioc::make('B', 'bb', ['this is param b']);

// 输出结果,可以看出依赖注入成功。
this is C->cc
params:this is param b
로그인 후 복사

위의 두 예를 보면 객체를 생성하거나 메서드를 호출할 때 필요하지 않다는 것을 알 수 있습니다. 클래스나 메서드를 아는 것은 해당 클래스에 따라 다릅니다. 리플렉션 메커니즘을 사용하면 필요한 클래스를 쉽게 자동으로 주입할 수 있습니다.

요약

알겠습니다. 위 코드가 매우 간단하다고 생각하시나요? 사실, PHP의 리플렉션 메커니즘에 익숙하다면, 종속성 주입은 구현하기 어렵지 않습니다. 이해의 편의를 위해 작성된 것입니다. 실제 프로젝트에서는 위반이 그렇게 간단하지 않습니다. 예를 들어, 인스턴스화된 클래스는 다음 번에 캐시됩니다. 필요한 경우 재초기화 등의 작업 대신 직접 사용할 수 있습니다. 하지만 일단 원칙을 이해하면 프로젝트의 필요에 따라 나머지 부분을 개선할 수 있다고 믿습니다.

위 내용은 PHP의 리플렉션 메커니즘을 이용한 자동 종속성 주입에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!