public function __invoke($request, &$response)
{
$args = array();
//绑定参数和返回值
$this->bind['param']->bind($request, $response, $args);
$this->bind['return']->bind($request, $response, $args);
//利用参数绑定的能力,提取@cache注释的信息
$cache_ttl = 0;
$cache_check = null;
$cache_res = new Response(array('ttl' => function ($param) use(&$cache_ttl) {
$cache_ttl = $param;
}, 'check' => function ($param) use(&$cache_check) {
$cache_check = $param;
}, 'body' => function ($_ = null) {
}));
$this->bind['cache']->bind($request, $cache_res, $args);
$use_cache = !$this->bind['cache']->isEmpty();
$given = count($args);
if ($given === 0) {
$required_num = 0;
} else {
ksort($args, SORT_NUMERIC);
end($args);
$required_num = key($args) + 1;
}
Verify::isTrue($given === $required_num, new BadRequest("{$this->ins->class}::{$this->method_name} {$required_num} params required, {$given} given"));
// 变量没给全
$cache_key = null;
if ($use_cache) {
//输入参数包括函数参数和类注入数据两部分
//所以以这些参数的摘要作为缓存的key
$injected = $this->ins->getInjected();
$cache_res->flush();
//取出cache参数
$cache_key = "invoke_{$this->ins->class}_{$this->method_name}_" . sha1(serialize($args) . serialize($injected) . $cache_ttl);
$succeeded = false;
$data = $this->checkAbleCache->get($cache_key, $succeeded);
if ($succeeded && is_array($data)) {
$response->setBuffer($data);
$response->flush();
Logger::info("{$this->ins->class}::{$this->method_name} get response from cache {$cache_key}");
return;
}
}
$impl = $this->ins->getImpl($request);
//
if (!$this->bind['throws']->isEmpty()) {
try {
$res = call_user_func_array(array($impl, $this->method_name), $args);
} catch (\Exception $e) {
$response->clear();
// 清除之前绑定的变量, 异常发生时可能已经写入了一些参数
$this->bind['throws']->bind($request, $response, $e);
$response['break'][][0] = true;
$response->flush();
return;
}
} else {
$res = call_user_func_array(array($impl, $this->method_name), $args);
}
$this->bind['return']->setReturn($res);
if ($use_cache) {
$this->checkAbleCache->set($cache_key, $response->getBuffer(), $cache_ttl, $cache_check);
Logger::info("{$this->ins->class}::{$this->method_name} set response to cache {$cache_key}, ttl={$cache_ttl}, check=" . ($cache_check === null ? 'null' : get_class($cache_check)));
}
$response->flush();
}