/** * 根据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; }
/** * 根据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; }