PHP 종속성 주입과 제어 역전의 두 가지 개념을 이해하려면 다음 문제를 이해해야 합니다.
DI——의존성 주입
IoC——제어 반전
1. 참가자는 누구인가요?
답변: 일반적으로 세 부분이 있는데, 하나는 객체이고, 다른 하나는 객체의 외부 리소스입니다. 명사에 대해 다시 설명하겠습니다. 객체는 일반적인 Java 객체를 참조하며, IoC/DI 컨테이너는 단순히 IoC/DI 기능을 구현하는 데 사용되는 프레임워크 프로그램을 참조합니다. 개체 외부에서 개체에 필요한 다른 개체 또는 개체에 필요한 파일 리소스 등과 같이 집합적으로 리소스라고 합니다.
2. 의존성: 누가 누구에게 의존하는가? 종속성이 있는 이유는 무엇입니까?
답변: 객체는 IoC/DI 컨테이너에 따라 다릅니다. 프로젝트에서는 다양한 클래스 사이에 다양한 관계가 존재하며, 이들 모두가 완전히 독립적일 수는 없으므로 종속성을 형성합니다. 기존 개발에서는 다른 클래스를 사용할 때 직접 호출을 사용했는데, 이는 강력한 결합을 형성하므로 피해야 합니다. 종속성 주입은 컨테이너를 빌려 종속 개체를 전송하여 분리를 달성합니다.
3. 주사: 누가 누구에게 주사하는가? 정확히 무엇을 주입하나요?
정답: 컨테이너를 통해 객체에 필요한 외부 리소스를 주입합니다
4. 통제의 역전: 누가 누구를 통제하는가? 무엇을 통제하나요? 왜 반전이라고 불리는가?
답변: IoC/DI의 컨테이너 제어 개체는 주로 개체 인스턴스 생성을 제어합니다. 반전은 양의 방향에 상대적이므로 양의 방향으로 간주되는 것은 무엇입니까? 일반적인 상황에서 애플리케이션을 생각해 보세요. A 내부에서 C를 사용하려면 어떻게 하시겠습니까? 물론 C의 객체는 직접 생성된다. 즉, 필요한 외부자원 C를 클래스 A에서 적극적으로 획득하는 상황을 포워드(forward)라고 한다. 그렇다면 반전은 무엇인가? 즉, 클래스 A는 더 이상 C를 적극적으로 획득하지 않고 IoC/DI 컨테이너가 C의 인스턴스를 획득할 때까지 수동적으로 기다린 다음 이를 역으로 클래스 A에 주입합니다.
5. 의존성 주입과 제어 역전은 같은 개념인가요?
답변: 위에서 볼 수 있듯이 종속성 주입은 애플리케이션의 관점에서 설명됩니다. 종속성 주입은 더 자세히 설명할 수 있습니다. 애플리케이션은 컨테이너에 따라 다릅니다. 필요한 외부 리소스를 생성하고 주입합니다. 제어 반전은 컨테이너의 관점에서 설명되지만 설명은 완료됩니다. 컨테이너는 애플리케이션을 제어하고 컨테이너는 반대로 애플리케이션에 필요한 외부 리소스를 애플리케이션에 주입합니다.
예제를 통한 종속성 주입의 일부 구현 방법을 자세히 살펴보겠습니다.
1. 생성자 주입
<?php class Book { private $db_conn; public function __construct($db_conn) { $this->db_conn = $db_conn; } }
2. 세터 주입
<?php class book{ private $db; private $file; function setdb($db){ $this->db=$db; } function setfile($file){ $this->file=$file; } } class file{} class db{} ... class test{ $book = new Book(); $book->setdb(new db()); $book->setfile(new file()); } ?>
위 두 메소드의 코드는 매우 명확하지만, 의존성을 많이 주입해야 할 경우에는 많은 라인을 추가해야 한다는 뜻이므로 관리가 어려울 것입니다.
더 나은 솔루션은 모든 종속성에 대한 컨테이너로 클래스를 생성하는 것입니다. 이 클래스에서는 필요한 종속성을 저장, 생성, 획득 및 찾을 수 있습니다.
<?php class Ioc { protected $db_conn; public static function make_book() { $new_book = new Book(); $new_book->set_db(self::$db_conn); //... //... //其他的依赖注入 return $new_book; } }
이때, 도서 인스턴스를 얻으려면 $newone = Ioc::makebook();만 실행하면 됩니다.
위는 컨테이너의 구체적인 예입니다. 특정 의존성 주입 방법을 작성하지 않는 것이 좋으며, 레지스트리 등록을 사용하여 획득하는 것이 좋습니다.
<?php class Ioc { /** * @var 注册的依赖数组 */ protected static $registry = array(); /** * 添加一个resolve到registry数组中 * @param string $name 依赖标识 * @param object $resolve 一个匿名函数用来创建实例 * @return void */ public static function register($name, Closure $resolve) { static::$registry[$name] = $resolve; } /** * 返回一个实例 * @param string $name 依赖的标识 * @return mixed */ public static function resolve($name) { if ( static::registered($name) ) { $name = static::$registry[$name]; return $name(); } throw new Exception('Nothing registered with that name, fool.'); } /** * 查询某个依赖实例是否存在 * @param string $name id * @return bool */ public static function registered($name) { return array_key_exists($name, static::$registry); } }
이제 다음 방법을 통해 등록하고 주입할 수 있습니다
<?php $book = Ioc::registry('book', function(){ $book = new Book; $book->setdb('...'); $book->setprice('...'); return $book; }); //注入依赖 $book = Ioc::resolve('book'); ?>
이상은 PHP 의존성 주입과 제어 반전에 대한 이해입니다. PHP 프로그래밍을 배우는 모든 분들에게 도움이 되길 바랍니다.