zoukankan      html  css  js  c++  java
  • PHP的高效IOC框架——CanoeDI

    PHP的高效IOC框架——CanoeDI

    一个非常简单且实用的IoC框架,相对于其他的Ioc框架有如下特点:

    1. 高效: 框架使用了非常实用且高效的算法,使得框架本身对应用的影响微乎其微,且框架提供了C扩展,最大限度的将性能提升到最高。
    2. 配置简单: 大多数情况下几乎不需要额外的配置
    3. 自动装配: 基于PHPDocument的property属性来自动装配
    4. 懒加载: 所有被注入的变量的实例都为即用即取, 不会产生内存垃圾
    5. IDE友好: 因为利用的是PHP的标准规范, 兼容大部分IDE

    安装

    编译安装,可以得到最大的效率:

    1
    2
    3
    4
    5
    6
    $ git clone https://github.com/dustinfog/canoe-di.git
    cd canoe-di/ext
    $ phpize
    $ ./configure
    make
    sudo make install

    而后编辑php.ini

    1
    2
    [canoe-di]
    extension=canoe_di.so

     composer安装 (生产环境如果已经编译安装了扩展,此步骤可省略。在开发环境,PHP源码可以让IDE提供代码完成提示,所以仍然推荐执行这一步):

    1
    composer require dustinfog/canoe-di

    使用

    获取实例

    1
    2
    3
    4
    5
    class ClassA
    {
    }
    //DI容器在处理类型时,会在第一次遇到的时候实例化,并且在以后使用中以单例的方式使用。
    $a = CanoeDIContext::get(ClassA::class);

    基于标注的装配

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    class ClassC
    {
    }
     
    use CanoeDIDITrait;
    use CanoeDIContext;
    /**
     * @property ClassC $c
     */
    class ClassA
    {
        //需要引入一个trait,用以处理$c的获取
        use DITrait;
     
        public function test() {
            //这里可以直接使用
            print_r($this->c);
        }
    }
     
     
    $a = Context::get(ClassA::class);
    $a->test(); //试一下会发生什么

    @uses标注:

    uses可以指定属性使用的类或者容器里的实例

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    interface InterfaceC {
        public function sayHello();
    }
     
     
    class ClassWorld implements InterfaceC
    {
        public function sayHello() {
            echo "hello, world! ";
        }
    }
     
     
    class ClassC implements InterfaceC
    {
        private $name;
     
        public function __construct($name)
        {
            $this->name = $name;
        }
     
        public function sayHello() {
            echo "hello, $name! ";
        }
    }
     
    use CanoeDIDITrait;
    use CanoeDIContext;
     
    /**
     * @property InterfaceC $c1 {@uses ClassWorld} //使用类名
     * @property InterfaceC $c2 {@uses c2} //使用容器内的ID
     */
    class ClassA
    {
        //需要引入一个trait,用以处理$c的获取
        use DITrait;
     
        public function test() {
            print_r($this->c1);
            print_r($this->c2);
        }
    }
     
    Context::set("c2"new ClassC("Bob"));
    // 更好的选择:Context::registerDefinition("c2", function(){new ClassC("Bob")})
     
    $a = Context::get(ClassA::class);
    $a->test(); //试一下会发生什么

    Singleton

    有时候,我们需要在一个非DI环境里有限的使用DI,这时候每个系统与DI容器的先借点都在调用Context::get()显得很丑陋,框架里提供了一个更加亲民的调用方式:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    use CanoeDISingletonTrait;
     
    class ClassA
    {
        use SingletonTrait;
    }
     
    $a = ClassA::getInstance();
    // 与Context::get(ClassA::class)等价,但隐藏了Context调用。
     
    $a = ClassA::getInstance("a1");
    // 与Context::get("a1")等价,但做了进一步的类型检查,即a1取到的实例与ClassA必须有"is a"的关系。

    预先定义

    上面的例子都是在运行时来实现自动装配的,但在某些时候可能需要手动预先创建一些定 义,以备后续使,框架提供了简单的支持.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    //注册类
    CanoeDIContext::registerDefinition('a', ClassA::class);
    //注册回调
    CanoeDIContext::registerDefinition(
        'b',
        function() {
            return new ClassB();
        }
    );
    //注册实例
    CanoeDIContext::set('c'new ClassC());

    配置

    大多数时候,预先定义都是写在配置文件里,可以用下列的方法加载配置:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    CanoeDIContext::loadConfig(
    [
        'definitions' => [ //这里是定义
            ClassB::class,
        ],
        'beans' => [ //这里可以预定义一些实际的值
            'uid' => 5,
        ],
    ]);
    转发 项目地址:https://github.com/dustinfog/canoe-di
  • 相关阅读:
    Write an algorithm such that if an element in an MxN matrix is 0, its entire row and column is set to 0.
    旋转二维数组
    replace empty char with new string,unsafe method和native implementation的性能比较
    判断一字符串是否可以另一字符串重新排列而成
    移除重复字符的几个算法简单比较
    也来纠结一下字符串翻转
    判断重复字符存在:更有意义一点
    程序员常去网站汇总
    sublime
    针对程序集 'SqlServerTime' 的 ALTER ASSEMBLY 失败,因为程序集 'SqlServerTime' 未获授权(PERMISSION_SET = EXTERNAL_ACCESS)
  • 原文地址:https://www.cnblogs.com/gh0408/p/6132235.html
Copyright © 2011-2022 走看看