视频地址 https://www.bilibili.com/video/BV14E411t7T4?p=8
原理就是给类加一个Bean的注释,这个类就可以用 ClassFactory::getBean获取配置好的实例
1 \anntest\app\core\ClassFactory.php
<?php /** * 类的加载器 */ namespace App\core; use App\annotations\Bean; use Doctrine\Common\Annotations\AnnotationReader; class ClassFactory { private static $bean =[]; public static function ScanBeans(string $path,string $nameSpace) { $phpfiles = glob($path."/*.php"); //var_dump($phpfiles); /*array(2) { [0]=> string(33) "/pro/anntest/app/test/MyRedis.php" [1]=> string(32) "/pro/anntest/app/test/MyUser.php" }*/ foreach ($phpfiles as $phpfile){ require ($phpfile); //get_declared_classes,返回由已定义类的名字所组成数组。 $classes = get_declared_classes(); $reader = new AnnotationReader(); //根据namespace过滤class foreach ($classes as $class){ if (strstr($class,$nameSpace)){ $refClass = new \ReflectionClass($class); /* var_dump($refClass);exit*/; //获取指定注释类型的注释 //getClassAnnotations 记得加s $annos = $reader->getClassAnnotations($refClass); foreach ($annos as $anno){ //instanceof 用于确定一个 PHP 变量是否属于某一类 class 的实例: if ($anno instanceof Bean){ self::$bean[$refClass->getName()] = self::loadClass($refClass->getName(),$refClass->newInstance()); } } } } } } public static function getBean(string $beanName) { if(isset(self::$bean[$beanName])) return self::$bean[$beanName]; return false ; } /** * @param $className * @param bool $object * * @return bool|object * @throws \Doctrine\Common\Annotations\AnnotationException * @throws \ReflectionException */ public static function loadClass($className,$object=false) { $refClass = new \ReflectionClass($className); //return $refClass->newInstance(); //获取所有的属性集合getClassAnnotation $properties = $refClass->getProperties(); foreach ($properties as $property){ $read = new AnnotationReader(); $annos = $read->getPropertyAnnotations($property); foreach ($annos as $anno){ //var_dump($anno); $getValue = $anno->do(); //实例化 //$obj = $refClass->newInstance(); $obj = $object ? $object : $refClass->newInstance(); //给属性赋值 $property->setValue($obj,$getValue); return $obj; } } //return false; return $object ? $object : $refClass->newInstance(); } }
2 anntest\app\annotations\Bean.php
必须加上这两行注释
/**
* @Annotation
* @Target({"CLASS"})
*/
<?php //类注释 Bean只能打在类上 用于类的自动加载 namespace App\annotations; /** * @Annotation * @Target({"CLASS"}) */ class Bean { }
3 anntest\app\test\MyRedis.php
3.1 使用Bean的命名空间
use App\annotations\Bean;
3.2 在类上加注释
/**
* @Bean()
*/
<?php /** * Created by PhpStorm. * User: SUN * Date: 2021/12/2 * Time: 22:48 */ namespace App\test; use App\annotations\Value; use App\annotations\Bean; /** * @Bean() */ class MyRedis { /** * @Value(name="url") */ public $conn_url; }
4 anntest\app\test\MyUser.php
再来一个类测试
<?php namespace App\test; use App\annotations\Bean; /** * @Bean() */ class MyUser { }
5 anntest\index.php 使用
<?php require_once __DIR__.'/vendor/autoload.php'; use \Doctrine\Common\Annotations\AnnotationRegistry; use \App\test\MyRedis; use \App\core\ClassFactory; //注册注释 AnnotationRegistry::registerLoader('class_exists'); //回调需返回true ClassFactory::ScanBeans(__DIR__.'/app/test','App\\test'); $myRedis = ClassFactory::getBean(MyRedis::class); var_dump($myRedis);