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;
}