如何在SPA中使用依赖注入?

时间:2011-06-16 20:25:01

标签: zend-framework configuration service dependency-injection soa

我目前正在使用SOA,我有很多服务,(ArticleService,CommentService,UserService等)。

我还有一个从XML配置文件中填充的ConfigurationService。

我正在使用Zend Framework。

我的某些服务需要配置服务,并且我正在使用依赖注入,这是一个很好的做法,在我的大多数服务的构造函数中添加ConfigurationService以便能够获取全局配置吗?

感谢您的反馈。

1 个答案:

答案 0 :(得分:3)

我会说,不,不要在其他服务的构造函数中传递配置容器 - 既不是服务也不是数组,也不传递Zend_Config实例。我会保留注入(无论是通过构造函数还是通过setter)来关注那些专注于实际需要的实际对象/协作者/数据的服务。

因此,例如,ArticleService可能依赖于ArticleRepository接口/对象或ArticleMapper或数据库适配器。让ArticleService的构造函数/ setter签名反映它真正需要的内容。

相反,我要做的是在Bootstrap期间,创建某种工厂对象 - 可能作为应用程序资源 - 在其构造函数中接受您的配置数据/对象/服务(或者更好的是,引导实例本身,您可以从中获取,不仅仅是您的配置数据,还有在引导过程中创建的任何应用程序资源,如数据库适配器)。然后在工厂对象上编写创建/提供所需其他服务的方法。在内部,工厂维护已创建服务的注册表,以便它可以在需要时延迟创建实例。

我想到的一个片段可能如下:

Bootstrap片段:

class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
    protected function _initFactory()
    {
        $factory = new My_Factory($this);
        return $factory;
    }
}

然后是工厂:

class My_Factory
{
    protected $_registry;

    protected $_bootstrap;

    public function __constructor($bootstrap)
    {
        $this->_bootstrap = $bootstrap;
    }

    public function getDbAdapter()
    {
       if (!isset($this->_registry['dbAdapter']){
           $this->_bootstrap->bootstrap('db');  // probably using app resource
           $this->_registry['dbAdapter'] = $This->_bootstrap->getResource('db');
       }
       return $this->_registry['dbAdapter'];

    }

    public function getArticleService()
    {
       if (!isset($this->_registry['articleService']){
           $dbAdapter = $this->getDbAdapter();
           $this->_registry['articleService'] = new My_ArticleService($dbAdapter);
       }
       return $this->_registry['articleService'];
    }

    public function getTwitterService()
    {
       if (!isset($this->_registry['twitterService']){
           $options = $this->_bootstrap->getOptions();
           $user = $options['twitter']['user'];
           $pass = $options['twitter']['pass'];
           $this->_registry['twitterService'] = new My_TwitterService($user, $pass);
       }
       return $this->_registry['twitterService'];
    }
}

然后在控制器中,您可以获取ArticleService实例:

class SomeController extends Zend_Controller_Action
{
    protected $_factory;

    public function init()
    {
        $this->_factory = $this->getInvokeArg('bootstrap')->getResource('factory');
    }

    public function someAction()
    {
        $articleService = $this->_factory->getArticleService();
        $this->view->articles = $articleService->getRecentArticles(5);  // for example
    }

}

这里的结果是每个服务都明确标识了它需要的协作者,工厂是一个负责创建/注入所有这些协作者的地方。

最后,我承认我只是在这里吐痰。对我来说,这基本上是一个基本的依赖注入容器;从这个意义上说,使用功能齐全的DIC - 可能是ZF2中的Symfony DIC或新的Zend\Di包 - 可能会更好。但经过几个月的努力,所有最好的做法建议注入你的依赖,这就是我想出的。如果这是愚蠢或者只是错误,请(请!)理顺我。 ; - )