一: hyperf 核心组件
二: Inject 实现原理
1: 通过InjectAspect代理了Inject注解
2: 具体执行逻辑扫,框架加载开始描所有的类,只要包含Inject注解的都会生成一个proxy类
3: ClassLoader 拦截Composer原始加载类方法,定位到proxy 文件类,通过__handlePropertyHandler 注入Inject注解的属性
代码块一
// Proxy the composer class loader
foreach ($loaders as &$loader) {
$unregisterLoader = $loader;
if (is_array($loader) && $loader[0] instanceof ComposerClassLoader) {
/** @var ComposerClassLoader $composerClassLoader */
$composerClassLoader = $loader[0];
AnnotationRegistry::registerLoader(function ($class) use ($composerClassLoader) {
return (bool) $composerClassLoader->findFile($class);
});
$loader[0] = new static($composerClassLoader, $proxyFileDirPath, $configDir, $handler);
}
spl_autoload_unregister($unregisterLoader);
}
代码块二
foreach ($classes as $className => $reflectionClass) {
$reflectionClassMap[$className] = $reflectionClass->getFileName();
if ($this->filesystem->lastModified($reflectionClass->getFileName()) >= $lastCacheModified) {
/** @var MetadataCollector $collector */
foreach ($collectors as $collector) {
$collector::clear($className);
}
$this->collect($annotationReader, $reflectionClass);
}
}
$this->loadAspects($lastCacheModified);
.....
.....
// Get the class map of Composer loader
$classMap = array_merge($reflectionClassMap, $classMap);
$proxyManager = new ProxyManager($classMap, $proxyDir);
$proxies = $proxyManager->getProxies();
以IndexController为例
class IndexController extends AbstractController
{
use \Hyperf\Di\Aop\ProxyTrait;
use \Hyperf\Di\Aop\PropertyHandlerTrait;
function __construct()
{
if (method_exists(parent::class, '__construct')) {
parent::__construct(...func_get_args());
}
$this->__handlePropertyHandler(__CLASS__);
}
/**
* @Inject()
* @var BaseService
*/
public $someService1;
/**
* @return array
*/
public function index()
{
$this->someService1->index();
$user = $this->request->input('user', 'Hyperf');
$method = $this->request->getMethod();
//var_dump($this);
return ['method' => $method, 'message' => "Hello {$user}."];
}
}
__handlePropertyHandler 就是属性注入逻辑
三: IOC注入分为哪些方式
1: Inject注入
2: 函数或是构造参数注入,无需使用Inject注解
四: Aspect切面实现
1: 通过上述的loadAspects方法生成代理类,在runtime/container/proxy 文件夹下面
2: 执行时通过 self::__proxyCall 拦截运行方法,执行切面的process方法
3: InjectAspect比较特殊,不需要执行切面的process 处理逻辑
4: 案例代码块如下
class SomeService extends BaseService
{
use \Hyperf\Di\Aop\ProxyTrait;
use \Hyperf\Di\Aop\PropertyHandlerTrait;
function __construct()
{
if (method_exists(parent::class, '__construct')) {
parent::__construct(...func_get_args());
}
$this->__handlePropertyHandler(__CLASS__);
}
public function index()
{
$__function__ = __FUNCTION__;
$__method__ = __METHOD__;
return self::__proxyCall(__CLASS__, __FUNCTION__, self::__getParamsMap(__CLASS__, __FUNCTION__, func_get_args()), function () use($__function__, $__method__) {
});
}
}
五:Amqp 的@Consumer 和 apolle启动拉配置实现方式
1: 通过ConfigProvider listeners 参数注入配置,框架启动时会在预设点dispatcher 对应的event 事件注入的观察者
2: 常见的event有
3: apolle 同理如上
4: 所以实现自定义的插件需要提供ConfigProvider配置文件
六:框架中比较重要的两个命令
1: vendor:publish 用来发布配置文件,tp,laravel都有
2: package:discover 用来注入ServiceProvder,ioc中重要的一环,tp,laravel都有,hyperf 暂时未使用