Exemplo n.º 1
0
 /**
  * 根据id得到对象实例
  * //TODO 单实例间互相引用会是问题
  * @param string $id
  * @param array $properties 类属性, 覆盖配置文件中的属性  
  * @param callable $injector fun($src), 获取注入值的方法
  * @param callable $init fun($inst, &$got) 初始化实例, 在创建后, 调用构造函数前
  * @param array $construct_args 构造函数的参数
  * @return object
  */
 public function create($id, $construct_args = null, $properties = null, $injector = null, $init = null)
 {
     if ($properties === null) {
         $properties = array();
     }
     if ($construct_args === null) {
         $construct_args = array();
     }
     $ins = null;
     $is_singleton = false;
     $class_name = $this->getClassName($id);
     if (isset($this->conf[$id])) {
         $class = $this->conf[$id];
         $class_refl = new \ReflectionClass($class_name);
         // 如果是单例
         // 带构造参数的类不支持单例
         if (count($properties) === 0 && count($construct_args) === 0 && isset($class['singleton']) && $class['singleton']) {
             $is_singleton = true;
             if (isset($this->singletons[$id])) {
                 $ins = $this->singletons[$id];
                 Logger::info("get {$id}[{$class_name}] as singleton");
                 return $ins;
             }
         }
         if (isset($class['properties'])) {
             $properties = array_merge($class['properties'], $properties);
         }
         if (isset($class['pass_by_construct']) && $class['pass_by_construct']) {
             //属性在构造时传入
             Verify::isTrue(count($construct_args) === 0, "{$class_name} pass_by_construct");
             //构造时传输属性, 所以不能再传入其他构造参数
             //组合构造参数
             $construct_args = $this->buildConstructArgs($class_refl, $properties);
             $properties = array();
         }
     } else {
         $class_refl = new \ReflectionClass($class_name);
     }
     if (isset($class['pass_by_construct']) && $class['pass_by_construct']) {
         $ins = $class_refl->newInstanceArgs($construct_args);
         $meta = $this->getMetaInfo($class_refl);
         $this->injectDependent($class_refl, $ins, $meta, $properties, $injector);
     } else {
         $nti = new NewThenInit($class_refl);
         $ins = $nti->getObject();
         $meta = $this->getMetaInfo($class_refl);
         $this->injectDependent($class_refl, $ins, $meta, $properties, $injector);
         if ($init !== null) {
             $init($ins);
         }
         $nti->initArgs($construct_args);
     }
     if ($is_singleton) {
         $this->singletons[$id] = $ins;
     }
     Logger::info("create {$id}[{$class_name}] ok");
     return $ins;
 }
Exemplo n.º 2
0
 /**
  * 根据id得到对象实例
  * //TODO 单实例间互相引用会是问题
  * @param string $id
  * @param array $properties 类属性, 覆盖配置文件中的属性  
  * @param callable $injector fun($src), 获取注入值的方法
  * @param callable $init fun($inst, &$got) 初始化实例, 在创建后, 调用构造函数前
  * @param array $construct_args 构造函数的参数
  * @return object
  */
 public function create($id, $construct_args = null, $properties = null, $injector = null, $init = null)
 {
     if ($properties === null) {
         $properties = array();
     }
     if ($construct_args === null) {
         $construct_args = array();
     }
     $ins = null;
     $is_singleton = false;
     $class_name = $this->getClassName($id);
     if (isset($this->conf[$id])) {
         $class = $this->conf[$id];
         $class_refl = new \ReflectionClass($class_name);
         // 如果是单例
         // 带构造参数的类不支持单例
         if (count($properties) === 0 && count($construct_args) === 0 && isset($class['singleton']) && $class['singleton']) {
             $is_singleton = true;
             if (isset($this->singletons[$id])) {
                 $ins = $this->singletons[$id];
                 Logger::info("get {$id}[{$class_name}] as singleton");
                 return $ins;
             }
         }
         if (isset($class['properties'])) {
             $properties = array_merge($class['properties'], $properties);
         }
         if (isset($class['pass_by_construct']) && $class['pass_by_construct']) {
             //属性在构造时传入
             Verify::isTrue(count($construct_args) === 0, "{$class_name} pass_by_construct");
             //构造时传输属性, 所以不能再传入其他构造参数
             //组合构造参数
             $construct_args = $this->buildConstructArgs($class_refl, $properties);
             $properties = array();
         }
     } else {
         $class_refl = new \ReflectionClass($class_name);
     }
     if (!$is_singleton) {
         if (array_search($id, $this->create_stack) !== false) {
             $tmp = $this->create_stack;
             Verify::e("create {$id} failed, cyclic dependencies can only used with singleton. cyclic:" . print_r($tmp, true));
         }
         $this->create_stack[] = $id;
     }
     try {
         if (isset($class['pass_by_construct']) && $class['pass_by_construct']) {
             $ins = $class_refl->newInstanceArgs($construct_args);
             $meta = $this->getMetaInfo($class_refl);
             if ($is_singleton) {
                 $this->singletons[$id] = $ins;
             }
             $this->injectDependent($class_refl, $ins, $meta, $properties, $injector);
         } else {
             $nti = new NewThenInit($class_refl);
             $ins = $nti->getObject();
             $meta = $this->getMetaInfo($class_refl);
             if ($is_singleton) {
                 $this->singletons[$id] = $ins;
             }
             $this->injectDependent($class_refl, $ins, $meta, $properties, $injector);
             if ($init !== null) {
                 $init($ins);
             }
             $nti->initArgs($construct_args);
         }
     } catch (\Exception $e) {
         array_pop($this->create_stack);
         throw $e;
     }
     array_pop($this->create_stack);
     Logger::info("create {$id}[{$class_name}] ok");
     return $ins;
 }