Swoole实战之手撸HttpServer框架 8 构建框架的基本结构、Bean工厂基本设计、初步实现Bean注释

视频 https://www.bilibili.com/video/BV14E411t7T4?p=10

1 构建框架的基本结构

1.1 准备工作

2 代码

2.1 修改Request.php 

把之前的项目的Request.php文件复制过来,并修改命名空间为 :namespace Core\Http;  

2.2 修改composer.json

        "psr-4": {
            "App\\" : "app/" ,
            "Core\\":"core/"
        }
composer require doctrine/annotations 1.6
composer require nikic/fast-route 
composer require php-di/php-di

 然后别忘了执行

composer dump-autoload

2.3  env配置文件

配置扫描的路径

scan_dir = ./app/controllers
scan_root_namespace = App\

2.4 使用类注解

把原来的Bean.php复制过来

\core\annotations\Bean.php

<?php

namespace Core\annotations;
use Doctrine\Common\Annotations\Annotation\Target;
/**
 * @Annotation
 * @Target({"CLASS"})
 */
class Bean
{

}

2.5 使用属性注解

\core\annotations\Value.php

<?php

namespace Core\annotations;
use Doctrine\Common\Annotations\Annotation\Target;
/**
 * @Annotation
 * @Target({"PROPERTY"})
 */
class Value
{
    
}

2.6 注释的do方法 AnnotationHandler

\pro\core\annotations\AnnotationHandler.php

<?php

namespace Core\annotations;
return [
    //类注解
    Bean::class=>function($instance,$container){
        //get_class返回对象的类名
       $arr = explode("\\",get_class($instance));
       $beanName = end($arr);
       $container->set($beanName,$instance);
    },
    //属性注解
    Value::class=>function(){
    
    }
];

2.7 使用类注释要加载的类

\pro\app\controllers\UserController.php

<?php

namespace App\controllers;
use Core\annotations\Bean;

/**
 * Class UserController
 * 使用Bean注解加载类
 * @Bean()
 * @package App\controllers
 */
class UserController
{
    public $version = '1.0';
}

2.8  define.php

pro\app\config\define.php

<?php
//pro根目录 定义一个ROOT_PATH
define("ROOT_PATH",dirname(dirname(__DIR__)));
View Code

2.9 启动文件

pro\test.php

<?php
require_once __DIR__.'/vendor/autoload.php';
require_once __DIR__."/app/config/define.php";
\Core\BeanFactory::init();

$user = \Core\BeanFactory::getBean("UserController");
var_dump($user);

2.10 最重要的 \BeanFactory

pro\core\BeanFactory.php

<?php

namespace Core;


use DI\ContainerBuilder;
use \Doctrine\Common\Annotations\AnnotationReader;
use \Doctrine\Common\Annotations\AnnotationRegistry;


class BeanFactory
{
    
    //配置文件
    private static $env=[];
    //IOC容器
    private static  $container;
    
    //初始化函数
    public static function init()
    {
        self::$env = parse_ini_file(ROOT_PATH."/.env");
        //var_dump(self::$env);
        /**
         * array(2) {
        ["scan_dir"]=>
        string(17) "./app/controllers"
        ["scan_root_namespace"]=>
        string(4) "App\"
        }
         */
        //初始容器Builder
        $builder = new ContainerBuilder();
        //启用注释 主要是用它的Inject注释
        $builder->useAnnotations(true);
        //容器初始化
        self::$container=$builder->build();
        //扫描(重点)
        self::ScanBeans();
        
    }
    
    //获取env文件的配置内容
    private static function _getEnv(string $key,string $default='')
    {
        if (isset(self::$env[$key]))
            return self::$env[$key];
        return $default;
    }
    
    public static function ScanBeans()
    {
        $annoHandles = require_once (ROOT_PATH."/core/annotations/AnnotationHandler.php");
        $scanDir = self::_getEnv("scan_dir",ROOT_PATH."/app");
        $scanRootNamespace = self::_getEnv("scan_root_namespace","APP\\");
        //glob() 函数返回匹配指定模式的文件名或目录
        //搜索要扫描目录下的php文件 返回文件名称
        $files = glob($scanDir."/*.php");
        foreach ($files as $file){
            require_once $file;
        }
        //注释类对象
        
        $reader = new AnnotationReader();
        //AnnotationRegistry::registerAutoloadNamespace('Core\annotations');
        
        AnnotationRegistry::registerLoader('class_exists'); //回调需返回true
        //get_declared_classes返回由已定义类的名字所组成的数组
        foreach (get_declared_classes() as $class){
           if (strstr($class,$scanRootNamespace)){
               $refClass = new \ReflectionClass($class);
               //获取所有类的注释
               $classAnnos = $reader->getClassAnnotations($refClass);
               foreach ($classAnnos as $classAnno){
                   //根据注释的类型获取对应处理方法
                   $hander = $annoHandles[get_class($classAnno)];
                   $hander(self::$container->get($refClass->getName()),self::$container);
                   
                   
               }
               
           }
        }
    }
    
    public static function getBean($name)
    {
        return self::$container->get($name);
    }
}
原文地址:https://www.cnblogs.com/polax/p/15729692.html