代码改变世界

hyperf3框架原理

  虎背熊腰  阅读(717)  评论(1编辑  收藏  举报

一: 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: 切面可以代理注解和class两种类型
2: 被代理的类通过上述的loadAspects方法生成代理类,在runtime/container/proxy 文件夹下面
3: 如果是代理了方法相关的类或是注解执行时通过 self::__proxyCall 拦截运行方法,执行切面的process方法
4: 如果是代理了属性类型的注解的,不需要执行切面的process 处理逻辑,比如InjectAspect
5: 案例代码块如下

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 事件注入的观察者,Consumer 消费者就会被拉起
2: 常见的event有

3: apolle 同理如上
4: 所以实现自定义的插件需要提供ConfigProvider配置文件

六:框架中比较重要的两个命令

1: vendor:publish 用来发布配置文件,tp,laravel都有
2: package:discover 用来注入ServiceProvider,ioc中重要的一环,tp,laravel都有,hyperf 暂时未使用

相关博文:
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
点击右上角即可分享
微信分享提示