IOC 容器

IOC 容器是整个框架最核心的部分,负责服务的管理和解耦组件。

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

引入相关类

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

    闭包绑定

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

我们可以通过 bind 来绑定一个闭包,通过 make 来运行服务,第二次运行如果是单例则直接使用生成后的结果,否则会每次执行闭包的代码。

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

  1. public function testBindClosure()
  2. {
  3. $container = new Container();
  4. $container->bind('foo', function () {
  5. return 'bar';
  6. });
  7. $this->assertSame('bar', $container->make('foo'));
  8. }

闭包绑定单例

  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. $this->assertSame($singleton, $container->make('singleton'));
  10. }

类直接生成本身

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

  1. public function testClass()
  2. {
  3. $container = new Container();
  4. $this->assertInstanceOf(Test1::class, $container->make(Test1::class));
  5. }

类单例

类也可以注册为单例。

  1. public function testSingletonClass()
  2. {
  3. $container = new Container();
  4. $container->singleton(Test1::class);
  5. $this->assertSame($container->make(Test1::class), $container->make(Test1::class));
  6. }

接口绑定

可以为接口绑定实现。

  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. {
  4. }

Test2 定义

  1. namespace Tests\Di\Fixtures;
  2. class Test2 implements ITest2
  3. {
  4. }

Test3 定义

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

通过 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);
  7. }