Swoole实战之手撸HttpServer框架 3 依赖注入反转控制 、Ioc容器、第三方DI库

0 传统方法,正向控制

<?php
class MyDB
{
   private $db;
   public function __construct($connInfo)
   {
   }
   
   public function gueryForRows($sql)
   {
       return ['uid'=>111];
   }
}

class MyUser
{
    public $mydb;
    public function __construct($dsn)
    {
        //正向实例化 以myUser控制MyDB
        $this->mydb = new MyDB($dsn);
    }
    
    public function getAllUsers():array {
        return $this->mydb->gueryForRows('select * from users');
    }
}

$user = new MyUser('mysql:host=localhost');
$list = $user->getAllUsers();
var_dump($list);
View Code

缺点:过度耦合。

1 改进版本1.0 依赖注入、控制反转

<?php
class MyDB
{
   private $db;
   public function __construct($connInfo)
   {
   }
   
   public function gueryForRows($sql)
   {
       return ['uid'=>222];
   }
}

class MyUser
{
    public $mydb;
    //$dsn配置
    // 1 正向控制 public function __construct($dsn)
    public function __construct(MyDB $DB)
    {
        //1 正向实例化 以myUser控制MyDB
        //$this->mydb = new MyDB($dsn);
        //MyUser不会主动去实例化DB 控制顺序发生了反转 起到了解耦的目的
        $this->mydb = $DB;
    }
    
    public function getAllUsers():array {
        return $this->mydb->gueryForRows('select * from users');
    }
}

// $user = new MyUser('mysql:host=localhost');
$db = new MyDB('mysql:host=localhost');
//依赖注入 控制反转    向MyUser注入MyDB的实例
$user = new MyUser($db);


$list = $user->getAllUsers();
var_dump($list);

优点:MyUser不再主动创建MyDB实例,变成被动等待依赖注入。起到了解耦的目的

2 IoC容器2.0

<?php
class MyDB
{
   private $db;
   public function __construct($connInfo)
   {
   }
   
   public function gueryForRows($sql)
   {
       return ['uid'=>333];
   }
}

class MyUser
{
    public $mydb;
    //$dsn配置
    // 1 正向控制 public function __construct($dsn)
    public function __construct(MyDB $DB)
    {
        //1 正向实例化 以myUser控制MyDB
        //$this->mydb = new MyDB($dsn);
        //MyUser不会主动去实例化DB 控制顺序发生了反转 起到了解耦的目的
        $this->mydb = $DB;
    }
    
    public function getAllUsers():array {
        return $this->mydb->gueryForRows('select * from users');
    }
}

class ClassFactory
{
    //容器   用来存放实例化后的类
    private static $container = [];
    
    public  static function set(String $name,callable  $func){
       self::$container[$name] = $func;
    }
    
    public static function getObject(string $name){
       if (isset(self::$container[$name])){
           //执行匿名函数
           return (self::$container[$name])();
       }
       return null;
    }
}
// 1 正向控制
// $user = new MyUser('mysql:host=localhost');
// 2 控制反转
/*$db = new MyDB('mysql:host=localhost');
//依赖注入 控制反转    向MyUser注入MyDB的实例
$user = new MyUser($db);*/
// 3 IoC容器
// 3.1 往容器里注入mydb实例
ClassFactory::set('mydb',function (){
    return new  MyDB('mysql:host=localhost');
});
// 3.2 往容器里注入mydb实例
ClassFactory::set('my_user',function (){
    return new MyUser(ClassFactory::getObject('mydb'));
});
//3.3获取user实例
$user = ClassFactory::getObject('my_user');

$list = $user->getAllUsers();
var_dump($list);

IoC容器:为了让我们的代码更具维护性,把注入这个过程隐藏起来,放到了一个专门的“容器”里面管理

 在swoole出现之后,ClassFactory可以常驻内存。

3 第三方DI库3.0

安装

 composer require php-di/php-di

3.1 使用方式一:简单使用(手工方式)不推荐

<?php
require_once __DIR__.'/vendor/autoload.php';
class MyDB
{
   private $db;
   public function __construct($connInfo)
   {
   }
   
   public function gueryForRows($sql)
   {
       return ['uid'=>444];
   }
}

class MyUser
{
    public $mydb;
    //$dsn配置
    // 1 正向控制 public function __construct($dsn)
    public function __construct(MyDB $DB)
    {
        //1 正向实例化 以myUser控制MyDB
        //$this->mydb = new MyDB($dsn);
        //MyUser不会主动去实例化DB 控制顺序发生了反转 起到了解耦的目的
        $this->mydb = $DB;
    }
    
    public function getAllUsers():array {
        return $this->mydb->gueryForRows('select * from users');
    }
}

/*class ClassFactory
{
    //容器   用来存放实例化后的类
    private static $container = [];
    
    public  static function set(String $name,callable  $func){
       self::$container[$name] = $func;
    }
    
    public static function getObject(string $name){
       if (isset(self::$container[$name])){
           //执行匿名函数
           return (self::$container[$name])();
       }
       return null;
    }
}*/

// 1 正向控制
// $user = new MyUser('mysql:host=localhost');
// 2 控制反转
/*$db = new MyDB('mysql:host=localhost');
//依赖注入 控制反转    向MyUser注入MyDB的实例
$user = new MyUser($db);*/
// 3 IoC容器
// 3.1 往容器里注入mydb实例
/*ClassFactory::set('mydb',function (){
    return new  MyDB('mysql:host=localhost');
});
// 3.2 往容器里注入mydb实例
ClassFactory::set('my_user',function (){
    return new MyUser(ClassFactory::getObject('mydb'));
});
//3.3获取user实例
$user = ClassFactory::getObject('my_user');*/

//4 使用DI组件
$container = new DIContainer();

$container->set('mydb',function (){
    return new  MyDB('mysql:host=localhost');
});
$container->set('my_user',function (DIContainer $c){
    return new MyUser($c->get('mydb'));
});
$user = $container->get('my_user');

$list = $user->getAllUsers();
var_dump($list);

3.2 使用方式二:配置的方法加载类(推荐

D:seckillproapp estMyDB.php

<?php
/**
 * Created by PhpStorm.
 * User: SUN
 * Date: 2021/11/12
 * Time: 23:24
 */

namespace App	est;


class MyDB
{
    private $db;
    public function __construct($connInfo)
    {
    }
    
    public function gueryForRows($sql)
    {
        return ['uid'=>555];
    }
}
View Code

D:seckillproapp estMyUser.php

<?php
/**
 * Created by PhpStorm.
 * User: SUN
 * Date: 2021/11/12
 * Time: 23:25
 */

namespace App	est;


class MyUser
{
    public $mydb;
    //$dsn配置
    // 1 正向控制 public function __construct($dsn)
    public function __construct(MyDB $DB)
    {
        //1 正向实例化 以myUser控制MyDB
        //$this->mydb = new MyDB($dsn);
        //MyUser不会主动去实例化DB 控制顺序发生了反转 起到了解耦的目的
        $this->mydb = $DB;
    }
    
    public function getAllUsers():array {
        return $this->mydb->gueryForRows('select * from users');
    }
}
View Code

D:seckillproapp esteans.php

<?php
namespace App	est;
return [
  
  MyDB::class=>function (){
      return new   MyDB('mysql:host=localhost');
  },
    // my_user是我起的名,最好用   MyUser::class更规范化
/*  'my_user'=>function (DIContainer $c){
      return new MyUser($c->get(mydb));
  },*/
  MyUser::class =>function (DIContainer $c){
      return new MyUser($c->get(MyDB::class));
  }
];

D:seckillpro est.php

<?php
require_once __DIR__.'/vendor/autoload.php';

$builder = new DIContainerBuilder();
//扫描所有的配置
$builder->addDefinitions(__DIR__."/app/test/beans.php");
$container = $builder->build();

$user = $container->get(App	estMyUser::class);
//echo   App	estMyUser::class.'------';//App	estMyUser
$list = $user->getAllUsers();

var_dump($list);
原文地址:https://www.cnblogs.com/polax/p/15450154.html