dreamcat/container

窗口,依赖注解直接赋值

v3.1.0 2020-01-21 06:09 UTC

This package is auto-updated.

Last update: 2024-11-21 21:19:45 UTC


README

介绍

容器,通过注解直接赋值,减少构造函数中的操作

版本更新记录

2.0.0

  1. ID中支持标明是否重新构建、是否保留实例、指定使用范围的信息
  2. 注册时可以标明指定范围、是否保留实例的信息
  3. 注册时可以只传入工厂类名,在需要创建实例时再创建工厂
  4. 注册时可以添加对象属性赋值(如果注册时标明的是工厂,则是对工厂对象赋值)
  5. 增加范围容器,实例范围只在范围容器中出现
  6. 增加克隆魔术方法,克隆容器时不再复制已创建的实例,只保留配置信息

安装教程

composer require dreamcat/container

容器使用说明

  1. 创建容器,注入相应工厂方法、别名、实例

     <?php
     use DreamCat\Container\AnnotationDealer;
     use DreamCat\Container\HelperInfo\RegeditInfo;
     use DreamCat\Container\HelperInfo\ScopeRegeditInfo;
     
     // 容器常用方法说明,PSR 标准接口不列出
     class Container implements ContainerInterface {
         /**
          * 注册创建模式
          * @param string $id 实体标识
          * @param RegeditInfo $info 注册信息
          * @param bool $overwrite 是否覆盖原有设定
          * @return static 容器本身
          */
         public function regedit(string $id, RegeditInfo $info, bool $overwrite = true): Container {
            return $this;
         }
        
         /**
          * 直接注册一个实体对象
          * @param string $id 实体标识
          * @param mixed $object 实体对象
          * @return Container 容器本身
          */
         public function regeditInstance(string $id, $object): Container {
            return $this;
         }
         
          /**
           * 注册自定义注解处理器
           * @param string $annotation 注解名称
           * @param AnnotationDealer $annotationDealer 处理器
           * @return Container 容器本身
           */
          public function regeditAnnotation(string $annotation, AnnotationDealer $annotationDealer): Container {
             return $this;
          }
     }
       
     // 带范围功能的容器
     class ScopeContainer extends Container {
          /**
           * ScopeContainer constructor.
           * @param Container $globalContainer 全局容器
           */
          public function __construct(Container $globalContainer) {}
       
          /**
           * 注册创建模式
           * @param string $id 实体标识
           * @param ScopeRegeditInfo $info 注册信息
           * @param bool $overwrite 是否覆盖原有设定
           * @return static 容器本身
           */
          public function regedit(
              string $id,
              ScopeRegeditInfo $info,
              bool $overwrite = true
          ): ScopeContainer {
             return $this; 
          }
     }
    
  2. 在需要的时候调用容器的 get 方法即可获取对象,会将构造函数中参数通过容器获取并传入,逻辑如下:

    1. 如果函数声明中有默认参数直接使用默认参数
    2. 如果参数无类型声明,传入 null
    3. 如果参数类型是内置类型,传入默认值
      1. intfloat = 0
      2. string = ""
      3. array = []
      4. bool = false
      5. callable = function () {}
    4. 以参数类名为对象标识,在容器中获取对象
  3. 构造函数创建对象完成之后,遍历所有的属性(包括继承的),依据注解规则注入参数

  4. 所有注册类函数一定要先期调用,等调用过 get 方法之后,注册函数不一定生效

get($id) 方法的 id 结构说明

[crg|]id[::arg] 其中方括号的部分都是可选的

前缀的 c r q 顺序没有限制

  • c 存在此字符表示只做创建,无需在容器中保留
  • r 存在此字符表示不论原先是否有创建过,都是直接重新创建
  • g 仅在 ScopeContainer 中生效,表示在全局容器中创建

后缀的子参数 arg 仅在工厂模式下有意义,用于 create 方法的第二参数

注解说明

目前只支持注解加在属性上,不管是 publicprotectedprivate 都是可以的,但是 static 属性是无效的,无法注入

注意 所有不通过容器创建的对象,注解都是不生效的

  1. 加入注解 Autowire 且注解无参数声明,则类型依赖 var 注解。不支持内置类型(比如int),这些类型直接使用默认值即可。 注意类名如果不是以 \ 开始,则会首先在当前文件的 use 语句查找,然后在当前名空间查找,最后尝试全局
  2. 加入注解 Autowire 且注解后跟一个名称,则使用相应名称做为实体标识到容器中获取对象
  3. 如果加入自定义注解处理器,则将注解后面的字符串以空格隔开做为参数传入对应处理器,将返回值做为值注入属性
  4. 多个预期生效的注入注解,可能发生不可预期的情况
  5. 属性注入是不会检查是否已设定默认值,如果注入生效,会覆盖默认值

注解示例

<?php
class AnnotationDemo
{
    /**
     * @Autowire
     * @var Class1 $value1
     * @note 从容器中获取一个 Class1 对象注入
     */
    private $value1;
    /**
     * @Authwire db
     * @var Class2 $value2
     * @note 从容器中获取一个标识为 db 的对象注入
     */
    private $value2;
    /**
     * @Config db.username
     * @var string $value3
     * @note 调用 Config 注解的处理器
     */
    private $value3;
}

todo list

  1. 解决close事件可能被多次调用的问题
  2. 解决trait里声明的属性无法解析类型的问题