PHP가 리플렉션 메커니즘을 기반으로 자동 종속성 주입을 구현하는 방법에 대한 자세한 설명

*文
풀어 주다: 2023-03-18 08:36:01
원래의
1916명이 탐색했습니다.

이 글에서는 주로 리플렉션 메커니즘을 기반으로 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';
  }
}
로그인 후 복사


생성자의 테스트 종속성 주입

// 使用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) {
  }
 }
}
로그인 후 복사

테스트 메서드 종속성 주입

Ioc::make('B', 'bb', ['this is param b']);
// 输出结果,可以看出依赖注入成功。
this is C->cc
params:this is param b
로그인 후 복사


위의 두 예에서 우리는 객체를 생성하거나 메소드를 호출할 때 클래스 또는 이 메서드는 해당 클래스에 따라 달라집니다. 리플렉션 메커니즘을 사용하면 필요한 클래스를 쉽게 자동으로 주입할 수 있습니다.

요약

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


관련 읽기:

php 반사 사용 예제

PHP 반사 사용 예제 코드

동적 프록시

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

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