V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
lml12377
V2EX  ›  程序员

Phalcon 的 ioc 实现

  •  
  •   lml12377 · 2016-08-16 16:05:44 +08:00 · 2225 次点击
    这是一个创建于 3028 天前的主题,其中的信息可能已经有所发展或是发生改变。

    看 phalcon 的源码,关于 Di :

    假设:

    $di = new Di();
    
    // set
    $di->set('request', function(){
    	return new Request();
    });
    
    // get
    $request = $di->get('request');
    

    看了下大概流程:

    1 、 set() 创建 Service 对象

    2 、 get() 拿到之前创建的 Service 对象,调用 resolve(),里面 call_user_func() 执行匿名函数

    3 、 get() 里给组件 setDI($this) 并返回这个组件对象

    里面有个很奇怪的地方:

    resolve() 里面会用 \Closure::bind() 把 $di 对象交给匿名函数,接着才 call_user_func ,但是 $di->get() 里面却通过 setDI() 来注入 $di 对象,这是何必呢、、、

    既然把 $di 对象 bind() 回去了,我就可以在匿名函数里直接 return new Request($this); 啊,这样每个组件继承一个基类,基类的构造函数负责给自己的 protected $_di; 赋值啊、、、

    求解!

    di: https://github.com/phalcon/cphalcon/blob/master/phalcon/di.zep

    service: https://github.com/phalcon/cphalcon/blob/master/phalcon/di/service.zep

    第 1 条附言  ·  2016-08-16 16:42:25 +08:00

    另外还有个很奇怪的问题,shared 的组件是单例的,但是这个单例是针对于存放它的 Service,Di 中 setShared 创建出来的 Service 并不是单例的,而是直接覆盖的:

    let service = new Service(name, definition, shared),
    			this->_services[name] = service;
    
    3 条回复    2016-08-17 09:15:36 +08:00
    jerray
        1
    jerray  
       2016-08-16 20:22:52 +08:00   ❤️ 1
    1. 只有当 instance 实现了 InjectionAwareInterface 接口的时候才会执行 setDI 。通过 set 方法创建的 Service 对象并没有实现这个接口
    2. setShared 只是包装了一下 set : setShared(name, definition) -> set(name, definition, true)
    3. 这里的 Service 是具体实现的包装器,根据 definition resolve 出来的对象才是真正运行时用到的 Service
    4. shared 组件是单例的, Service 包装器在 resolve 的时候判断当前组件是否是单例,如果是并且已经实例化了,直接返回实例。如果未实例化,会根据 definition 进行实例化
    5. 看上去同一个名字的组件只能注册一个
    6. 我不会 Zephir

    好像并没有哪里奇怪
    bombless
        2
    bombless  
       2016-08-16 21:25:07 +08:00 via Android   ❤️ 1
    它在全局有个默认的 di ,估计最开始设计的时候是所有组件都用这个 di ,后面才改成这样的。

    我感觉 phalcon 很多地方都不符合直觉的
    lml12377
        3
    lml12377  
    OP
       2016-08-17 09:15:36 +08:00
    @jerray 还有个问题,这个 Di 只能算个容器吧,只不过装的 Service 对象(事实上 sharedInstances 装的是具体的组件对象),这也只能算是依赖倒置,并没有实现注入吧?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2584 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 03:36 · PVG 11:36 · LAX 19:36 · JFK 22:36
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.