PHP框架之容器

最近闲下来看了下YII2的源代码,并结合网上的资料对容器的概念有了新的理解。所谓容器就是承载东西的一个空间。那么在PHP主流框架中的容器就是装载类的一个储存空间。当然,并不仅仅只是装载而已,它还帮助我们实例化我们需要的对象。但是,PHP框架中的容器并不只是简单的装载和生成对象的功能,它还帮助我们自动解决了依赖的问题。我们都知道,实例化一个对象的时候,会调用构造方法,不管是隐式的默认构造方法还是显式的自定义的构造方法。那么如果在构造方法的参数列表中,包含有类这样的形参,那么容器会自动帮我们把形参转换成对象。并让构造方法顺利执行,完成实例化对象。容器的这两种行为就产生了一下的两个概念:

  DI(Dependency Injection):依赖注入。对象实例化,调用带有参数列表的构造函数,没有这些参数,对象无法实例化,这些参数即为依赖。把参数进行处理并通过反射方法实例化对象,这个过程就是注入

  ICO(Inversion of Control):控制反转。对象的创建一般都是通过"new"关键字进行实例化,现在通过容器自动把我们实例化对象。类实例化的控制权发生了转移,即控制反转。

  通过对容器的理解和YII源码的参考,为了加深理解,自己也动手写了一段模拟代码:

/**
    **    容器
    **/
    class Container{

        /**
        **    注册映射
        **/
        private $binds = [];

        /**
        **    缓存类反射对象
        **/
        private $reflections = [];

        /**
        **    类依赖缓存
        **/
        private $dependents = [];

        /**
        **    注册类声明
        **    @param    string    $class    类名
        **    @param    string|array|Closure    $declaration    类声明定义
        **    @param    array    $params    参数数组
        **/
        public function bind($class,$declaration){
            $this->binds[$class] = $declaration;

            //获取类构造函数的参数列表,即实例化对象的依赖关系
            $this->setDependents($class);
        }

        /**
        **    获取类的实例化对象
        **/
        public function get($class,$params=null){
            /**
            **    确保已注册了类声明信息
            **/
            if(isset($this->binds[$class])){

                /**
                **    解决依赖,用于把构造函数里面的依赖对象进行实例化
                **/
                $this->resolveDependents($class);

                /**
                **    DI(依赖注入):把准备好的构造函数的参数列表数组通过反射的方法注入到类的构造函数中,进行对象实例化
                    IOC(控制反转): 通过容器来实例化对象,并返回
                **/
                $reflectionClassObj = $this->reflections[$class];
                $obj = $reflectionClassObj->newInstanceArgs($this->dependents[$class]);

                //返回对象
                return $obj;
            }else{
                /**
                **    Code:当未注册到容器,则直接实例化对象
                **/
                throw new \Exception("Not find " . $class . " from container");
                exit(1);
            }
        }

        /**
        **    设置类的依赖,并保存ReflectionClass对象
        **/
        public function setDependents($class){
            if(!isset($this->dependents[$class])){
                $reflectionClassObj = new ReflectionClass($class);

                /**
                **    缓存类的ReflectionClass对象
                **/
                $this->reflections[$class] = $reflectionClassObj;

                /**
                **    通过反射获取类的构造函数参数信息列表,简称为依赖,并缓存依赖信息。
                **/
                $constructor = $reflectionClassObj->getConstructor();
                if(!is_null($constructor)){
                    $params = $constructor->getParameters();
                    $this->dependents[$class] = $params;
                }else{
                    $this->dependents[$class] = [];
                }
            }
        }

        /**
        **    解析依赖
        **/
        public function resolveDependents($class){
            if(isset($this->dependents[$class])){
                $dependents = $this->dependents[$class];
                foreach($dependents as $k=>$v){
                    //如果不为NULL,则表示这个参数是一个类,接口,则进行实例化
                    if($v->getClass() != null){
                        $this->dependents[$class][$k] = $this->get($v->getName());
                    }
                }
            }
        }
    }

    /**
    **    Database操作类
    **/
    class Db{

        public function find(){
            echo "~~~~~~Search~~~~~~";
        }

    }

    /**
    **    用户操作Model
    **/
    class User{

        private $db;

        public function __construct(Db $db){
            $this->db = $db;
        }

        public function findAll(){
            $this->db->find();
        }
    }

    //注册到容器
    $container = new Container();
    $container->bind(‘db‘,‘Db‘);
    $container->bind("user","User");

    $user = $container->get("user");    //获取User对象,容器自动解决依赖并创建对象
    $user->findAll();                           //echo "~~~~~~Search~~~~~~",也表示实例化的时候,也注入了Db对象
时间: 2024-10-24 04:37:20

PHP框架之容器的相关文章

有Ceph、GlusterFS等分布式存储的实际开发和应用经验,Openstack Cinder框架、容器卷管理方案如Flocker

岗位职责:参与构建云存储服务,包括开发.设计和运维工作?. 任职要求:1.本科及以上,3年以上存储系开发.设计或运维工作经验:2.熟练操作Linux系统并对内核比较了解:对云计算.虚拟化有所了解:3.有Ceph.GlusterFS等分布式存储的实际开发和应用经验:4.至少精通JAVA.Python.Ruby.C/C++.Go等语言之一,具备较强的开发能力和技巧:5.有参与过云平台或大型互联网系统底层平台开发设计者优先:参与过开源代码项目贡献的优先:6.喜欢钻研技术,想从事云计算的开发设计和运维工

跟着刚哥学习Spring框架--Spring容器(二)

Spring容器 启动Spring容器(实例化容器) -- IOC容器读取Bean配置创建Bean实例之前,必须对它进行实例化(加载启动),这样才可以从容器中获取Bean的实例并使用.  Bean是Spring管理的基本单位,任何的Java对象和组件都被当成Bean处理,容器还负责管理Bean与Bean之间的依赖关系.  两种类型的启动实现   1.BeanFactory:IOC容器的基本实现,是Spring框架的基础设施,面向Spring本身: -- Spring容器最基本的接口就是BeanF

【SSH进阶之路】一步步重构容器实现Spring框架——解决容器对组件的“侵入式”管理的两种方案--主动查找和控制反转(九)

目录 [SSH进阶之路]一步步重构容器实现Spring框架--从一个简单的容器开始(八) [SSH进阶之路]一步步重构容器实现Spring框架--解决容器对组件的"侵入式"管理的两种方案--主动查找和控制反转(九) [SSH进阶之路]一步步重构容器实现Spring框架--配置文件+反射实现IoC容器(十)(未更新) [SSH进阶之路]一步步重构容器实现Spring框架--彻底封装,实现简单灵活的Spring框架(十一)(未更新) 对于IOC的原理,我们曾经写过一篇博文,[SSH进阶之路

GUI——AWT框架和容器,创建简单窗体

GUI概述:GUI(Graphical User Interface)—图形化用户界面.用户和程序之间可以通过GUI能方便友好地进行交互,在Java语言中,JFC(Java Foundation Classed)是开发GUI的API集,它主要包含以下几个部分: a)   AWT(抽象窗口工具包):Java开发用户界面最初的工具包,是建立JFC的主要基础; b)   Swing组件:建立在AWT之上,新的,功能更强大的图形组件包; c)   JAVA 2D:实现高质量的二维图形; AWT框架: ①

day14 集合框架--ArrayList容器

集合框架:Collection 为什么会出现这么多的容器呢?因为每一个容器对数据的存储方式都有不同,这个存储方式称之为:数据结构 CollectionDemo 创建一个集合容器.使用Collection接口的子类,ArrayList /*1,add方法的参数类型是Object.以便于接受任意类型对象.    2,集合中存储的都是对象的引用(地址) */ import java.util.*; class CollectionDemo { public static void main(Strin

Spring框架IOC容器和AOP解析

主要分析点: 一.Spring开源框架的简介  二.Spring下IOC容器和DI(依赖注入Dependency injection) 三.Spring下面向切面编程(AOP)和事务管理配置  一.Spring开源框架的简介  Spring是一个开源框架,Spring是于2003 年兴起的一个轻量级的Java 开发框架,由Rod Johnson 在其著作Expert One-On-One J2EE Development and Design中阐述的部分理念和原型衍生而来.它是为了解决企业应用开

唯品会RPC服务框架与容器化演进--转

原文地址:http://mp.weixin.qq.com/s?__biz=MzAwMDU1MTE1OQ==&mid=405781868&idx=1&sn=cbb10d37e25c76a1845f593a222da3c9&scene=0#wechat_redirect 编者按:本文是邱戈川在 3 月 27 日数人云"百万并发"活动的演讲,授权「高可用架构」首发.转载请注明来自高可用架构公众号「ArchNotes」.   邱戈川,唯品会分布式架构平台产品经理

【38】java的集合框架(容器框架)

Collection接口 Collection是最基本的集合接口,一个Collection代表一组Object,即Collection的元素(Elements).一些 Collection允许相同的元素而另一些不行.一些能排序而另一些不行.Java SDK不提供直接继承自Collection的类,Java SDK提供的类都是继承自Collection的"子接口"如List和Set. 所有实现Collection接口的类都必须提供两个标准的构造函数:无参数的构造函数用于创建一个空的Col

Spring框架—— IOC容器和Bean的配置

 1 IOC和DI ①IOC(Inversion of Control):反转控制. 在应用程序中的组件需要获取资源时,传统的方式是组件主动的从容器中获取所需要的资源,在这样的模式下开发人员往往需要知道在具体容器中特定资源的获取方式,增加了学习成本,同时降低了开发效率. 反转控制的思想完全颠覆了应用程序组件获取资源的传统方式:反转了资源的获取方向--改由容器主动的将资源推送给需要的组件,开发人员不需要知道容器是如何创建资源对象的,只需要提供接收资源的方式即可,极大的降低了学习成本,提高了开发的效