用注解的方式注册一个定时任务
效果演示
相关配置
return [
/**
* 注解
* @see \Corona\Providers\AttributeServiceProvider::class
* namespaces 规定了需要扫描的命名空间, annotate 注册注解
*/
'attribute' => [
'namespaces' => [
'Corona\Timer'
],
'annotate' => [
Corona\Attributes\Scheduled::class
]
],
];
注解
#[Attribute(Attribute::TARGET_METHOD)]
class Scheduled implements ContextualAttribute
{
/**
* @param String $cron
* @param String $desc
*/
public function __construct(private readonly String $cron,
private readonly String $desc = '')
{
}
public static function resolve(self $attribute, ReflectionMethod $method): void
{
Schedule::call(fn() => app($method->class)->{$method->name}())
->cron($attribute->cron)
->name(sprintf('%s@%s', $method->class, $method->name))
->description($attribute->desc);
}
}
AttributeServiceProvider
class AttributeServiceProvider extends ServiceProvider
{
/**
* @throws \ReflectionException
* @throws DdException
*/
public function register()
{
// 扫描目录
if (!file_exists($classMapPath = base_path('vendor/composer/autoload_classmap.php'))){
return;
}
// 符合条件的类
$classMap = Collection::make(require $classMapPath)->filter(function ($classPath, $classes){
foreach (config('corona.attribute.namespaces', []) as $item) {
if (str_starts_with($classes, $item)){
// 跳过接口、抽象类、trait
if (!(new \ReflectionClass($classes))->isInstantiable()) {
continue;
}
return true;
}
}
return false;
});
foreach (config('corona.attribute.annotate') as $item) {
foreach ($classMap->keys() as $classes) {
// 处理类注解
$ref = new \ReflectionClass($classes);
// 处理属性注解
foreach ($ref->getAttributes($item) as $attribute) {
$attribute->newInstance()::resolve($attribute->newInstance(), $classes);
break;
}
// 处理方法注解
foreach ($ref->getMethods() as $method) {
foreach ($method->getAttributes($item) as $attr) {
$attr->newInstance()::resolve($attr->newInstance(), $method);
}
}
}
}
}
}
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: