<?php declare(strict_types=1); ini_set('display_errors', 'On'); error_reporting(-1); /** * MyInject类 */ #[Attribute(Attribute::TARGET_PROPERTY)] // 声明MyInject类是注解类 class MyInject { } /** * Human类 */ class Human { private string $name; // 姓名 #[MyInject] // 使用注解注入对象,无需手动创建对象即可直接使用 private Mobile $mobile; // Mobile对象 /** * 构造方法 * * @param string $name 姓名 */ public function __construct(string $name) { $this->name = $name; } /** * 打电话 * * @param string $num 通话目标号码 * @return void */ public function call(string $num): void { echo "{$this->name}即将打电话" . PHP_EOL; $this->mobile->dial($num); } } /** * 手机类 */ class Mobile { /** * 拨号 * * @param string $num 号码 * @return void */ public function dial(string $num): void { echo "手机拨号:$num" . PHP_EOL; } } // 要调用方法(类名+方法名) $class = 'Human'; $method = 'call'; // 相关参数 $name = '张三'; $num = '18888888888'; // 反射Human类 try { $reflectionClass = new ReflectionClass($class); } catch (ReflectionException $e) { exit('ReflectionException: ' . $e->getMessage()); } // 创建Human类实例(对象) $humanInstance = $reflectionClass->newInstanceArgs([$name]); $properties = $reflectionClass->getProperties(); // 获取Human类的所有属性并遍历 foreach ($properties as $property) { $attributes = $property->getAttributes(); // 获取属性的所有注解(单个属性可以有多个注解),如果属性有注解则处理 if ($attributes) { // 开始遍历该属性的所有注解并执行注解对应操作 foreach ($attributes as $attribute) { // 注解名为MyInject,说明该属性需要注入对象 if ($attribute->getName() === 'MyInject') { // 获取属性的类名 $typename = $property->getType()->getName(); // string(6) "Mobile" // 通过类名创建实例(对象),也是使用反射创建,而不是通过new关键字创建 try { $rc = new ReflectionClass($typename); } catch (ReflectionException $e) { exit('ReflectionException: ' . $e->getMessage()); } $instance = $rc->newInstance(); // 【注解注入核心代码】设置Human实例(对象)的$mobile属性值 $property->setValue($humanInstance, $instance); } } } } // 通过反射调用方法 try { $reflectionMethod = $reflectionClass->getMethod($method); } catch (ReflectionException $e) { exit('ReflectionException: ' . $e->getMessage()); } $reflectionMethod->invokeArgs($humanInstance, [$num]); // 张三即将打电话 // 手机拨号:18888888888 //========== 总结 ==========// // 1、注解注入可以让代码变得很简洁,当一个类有大量依赖类时不再需要每个依赖类都手动创建对象,只要加上注解即可直接使用对象。 // 2、注解因为要使用反射来解析,所以执行效率会稍低。
Copyright © 2024 码农人生. All Rights Reserved