<?php declare(strict_types=1); ini_set('display_errors', 'On'); error_reporting(-1); /** * MyAttribute类(自定义注解类) */ #[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD)] // 声明MyAttribute类为注解类,且限制该注解类目标只能是类和方法 class MyAttribute { private string $desc; public function __construct(string $desc) { $this->desc = $desc; } /** * @return string */ public function getDesc(): string { return $this->desc; } } /** * MyClass类 */ #[MyAttribute('这是MyClass类')] // 对MyClass类使用MyAttribute注解 class MyClass { #[MyAttribute('这是MyClass::myMethod()方法')] // 对MyClass::myMethod()方法使用MyAttribute注解 public function myMethod(): void { echo 'MyClass::myMethod()方法被调用'; } } //========== 通过反射类获取该类的注解 ==========// $reflectionClass = new ReflectionClass(MyClass::class); // 反射MyClass类 $attributes = $reflectionClass->getAttributes(); // 获取MyClass类的全部注解(该类只使用了MyAttribute注解) foreach ($attributes as $attribute) { $attributeInstance = $attribute->newInstance(); // 创建注解类实例,由于该类只使用了MyAttribute注解,实际上就是MyAttribute实例 $class1 = $reflectionClass->getName(); // 类名,就是MyClass $class2 = $attributeInstance::class; // 注解类名,就是MyAttribute $desc = $attributeInstance->getDesc(); echo "{$class1}类的{$class2}注解desc为:$desc" . PHP_EOL; // MyClass类的MyAttribute注解desc为:这是MyClass类 } //========== 通过反射方法获取该方法的注解 ==========// $reflectionMethod = $reflectionClass->getMethod('myMethod'); // 反射MyClass::myMethod()方法 $attributes = $reflectionMethod->getAttributes(); // 获取MyClass::myMethod()方法的全部注解(该方法只使用了MyAttribute注解) foreach ($attributes as $attribute) { $attributeInstance = $attribute->newInstance(); // 创建注解类实例,由于该方法只使用了MyAttribute注解,实际上就是MyAttribute实例 $method = $reflectionMethod->getName(); // 方法名 $class1 = $reflectionMethod->class; // 类名,就是MyClass $class2 = $attributeInstance::class; // 注解类名,就是MyAttribute $desc = $attributeInstance->getDesc(); echo "$class1::$method()方法的{$class2}注解desc为:$desc" . PHP_EOL; // MyClass::myMethod()方法的MyAttribute注解desc为:这是MyClass::myMethod()方法 } //========== 总结 ==========// // 1、PHP注解本质仍然是注释,既然是注释就不会影响程序执行,而Java注解本身是程序,它会影响程序执行,这是PHP注解和Java注解最大不同。 // 2、PHP注解需要依赖反射将其解析才有意义,否则注解就只是一段普通注释而已。 // 3、注解的目标可以是函数、类、类常量、类属性、类方法等,只要是声明式代码都可以对其使用注解。 // 4、对目标使用注解的格式(无参)为“#[注解名]”,注解可以设置参数,示例:#[MyAttribute('张三', '男', 2003)]。 // 5、对目标使用注解其实很像创建注解类对象,只是省略了new关键字。 // 6、注解常见使用场景是路由和注入,尤其是注入,很多框架都会使用注解注入实现解耦。 // 7、注解一般是写框架或基于支持注解框架写业务才会使用,否则很少会使用。
Copyright © 2024 码农人生. All Rights Reserved