小白兔晒黑了

导航

 

视频地址 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();
     }
}
View Code

2 anntest\app\annotations\Bean.php

 必须加上这两行注释

/**
* @Annotation
* @Target({"CLASS"})
*/


<?php

//类注释 Bean只能打在类上    用于类的自动加载
namespace App\annotations;

/**
 * @Annotation
 * @Target({"CLASS"})
 */
class Bean
{
    
}
View Code

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;

     
}
View Code

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);
 

 

 

posted on 2021-12-22 00:50  小白兔晒黑了  阅读(63)  评论(0编辑  收藏  举报