IOC 容器

    目前系统所有的关键服务都接入了 IOC 容器,包括控制器、Console 命令行。

    引入相关类

    • use Leevel\Di\Container;
    • use Leevel\Di\ICoroutine;
    • use stdClass;

    闭包属于惰性,真正使用的时候才会执行。

    通常来说,系统大部分服务都是单例来提升性能和共享。

    闭包绑定单例

    1. public function testSingletonClosure()
    2. {
    3. $container = new Container();
    4. $singleton = new stdClass();
    5. $container->singleton('singleton', function () use ($singleton) {
    6. return $singleton;
    7. });
    8. $this->assertSame($singleton, $container->make('singleton'));
    9. }

    一个独立的类可以直接生成,而不需要提前注册到容器中。

    1. public function testClass()
    2. {
    3. $container = new Container();
    4. }

    类单例

    类也可以注册为单例。

    1. public function testInterface()
    2. {
    3. $container = new Container();
    4. $container->bind(ITest2::class, Test2::class);
    5. $this->assertInstanceOf(ITest2::class, $container->make(ITest2::class));
    6. $this->assertInstanceOf(ITest2::class, $container->make(Test2::class));
    7. }

    接口绑定接口作为构造器参数

    接口可以作为控制器参数来做依赖注入。

    ITest2 定义

    1. namespace Tests\Di\Fixtures;
    2. interface ITest2
    3. {

    Test2 定义

    1. namespace Tests\Di\Fixtures;
    2. class Test3 implements ITest3
    3. public $arg1;
    4. public function __construct(ITest2 $arg1)
    5. {
    6. $this->arg1 = $arg1;
    7. }
    8. }

    通过 Test3 的构造函数注入 ITest2 的实现 Test2,通过 IOC 容器可以实现代码解耦。

    1. public function testInterface2()
    2. {
    3. $container = new Container();
    4. $container->bind(ITest2::class, Test2::class);
    5. $this->assertInstanceOf(ITest2::class, $test2 = $container->make(Test3::class)->arg1);
    6. $this->assertInstanceOf(Test2::class, $test2);