对hyperf的container和AOP的理解
Container
⾸先依赖注⼊就是为了降低耦合, 所以⽐如你需要⼀个 UserService , 本来定义了类 UserService , 那么直接调⽤就好了。 但是万⼀哪天想⽤的是 UserPlanBService
于是你要改所有 new UserService的地⽅, 很⿇烦,也就是紧耦合了
即使你通过类的构造函数 或者 注解 @inject 的地⽅,但是也要去⽐较多的地⽅修改,⽽且还不⼀定是哪个⽂件引⽤了
先说结论是: hyperf 做到了你只需要修改 config/autoload/dependencies.php 这个⽂件就能实现调⽤不同的 UserService。
<?php
return[
\App\Service\UserServiceInterface::class=> \App\Service\UserService::class];
再次细说:
你希望能够把 UserService 解耦, 但是业务上⽐如需要 UserService 的 getInfoById() 这个接⼝,那么⽆论你怎么更换UserPlanNService ,都必须实现这个接⼝,否则程序就运⾏不下去了。
因此定义⼀个 Interface 就呼之欲出了。 那么以后你只要注⼊ 这个 interface , ⽽且 dependence 指定了具体实现在哪 ,所以也就做到了 解耦。
继续深⼊,上述虽然解耦了 但是不够灵活,不能处理更复杂的情况,⽐如 UserService 在实例化的时候需要判断配置⽂件是否开启了缓存(构造函数初始化可以更加的灵活)那么实现思路⾃然是⼯⼚类,即在 UserService 上再加⼀层
代码⽰例:
<?php
namespace App\Service;
use Hyperf\Contract\ConfigInterface;use Psr\Container\ContainerInterface;
class UserServiceFactory{
// 实现⼀个 __invoke() ⽅法来完成对象的⽣产,⽅法参数会⾃动注⼊⼀个当前的容器实例
public function__invoke(ContainerInterface $container)
{
$config=$container->get(ConfigInterface::class);
// 我们假设对应的配置的 key 为 able
$enableCache=$config->get('able',false);
// make(string $name, array $parameters = []) ⽅法等同于 new ,使⽤ make() ⽅法是为了允许 AOP 的介⼊,⽽直接 new 会导致 AOP ⽆法正常介⼊流程return make(UserService::class,compact('enableCache'));
}}
<?php
namespace App\Service;
class UserService implements UserServiceInterface{
/**
* @var bool
*/
private$enableCache;
public function__construct(bool $enableCache)
{
// 接收值并储存于类属性中
$this->enableCache=$enableCache;
}
public function getInfoById(int $id)
{
return(new Info())->fill($id);
}}
那么绑定关系就是绑定⼯⼚类了
<?php
return[
\App\Service\UserServiceInterface::class=> \App\Service\UserServiceFactory::class];
上述这些也就是 hyperf 的 container 做的事情,如果你直接调⽤ new UserService 肯定是不⾏的。
AOP - ⾯向切⾯编程
⽤通俗的话来讲,就是在 Hyperf ⾥可以通过 切⾯(Aspect) 介⼊到任意类的任意⽅法的执⾏流程中去,从⽽改变或加强原⽅法的功能,这就是 AOP。
⼤致可以参考 hyperf/cache 提供的使⽤ AOP 的⽅法 , 代码:vendor/hyperf/cache/src/Aspect/CacheableAspect.php
⼤致应该就是 缓存切⼊注解
public$annotations=[
Cacheable::class,
];
发现有 Cacheable::class 这个注解的,(也就是 @Cacheable()) 则切⼊
// 获取类相关信息
$className=$proceedingJoinPoint->className;
$method=$proceedingJoinPoint->methodName;
$arguments=$proceedingJoinPoint->arguments['keys'];
// 获取缓存的 key , ttl 等
[$key,$ttl,$group,$annotation]=$this->annotationManager->getCacheableValue($className,$method,$arguments);
// 获取使⽤的缓存驱动
$driver=$this->manager->getDriver($group);
// 查缓存,命中直接返回,未命中则继续执⾏原有函数
cacheable[$has,$result]=$driver->fetch($key);
if($has){
return$result;
}
// 执⾏原有函数
$result=$proceedingJoinPoint->process();
// 根据之前获取的 key ttl 等设置缓存
$driver->set($key,$result,$ttl);
if($driver instanceof KeyCollectorInterface &&$annotation instanceof Cacheable &&$annotation->collect){
$driver->addKey($annotation->prefix.'MEMBERS',$key);
}
return$result;
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论