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

发布于 2024-11-15 14:17:21 字数 254 浏览 1 评论 0原文

我目前正在使用 SOA,我有一堆服务(ArticleService、CommentService、UserService 等)。

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

我正在使用 Zend 框架。

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

感谢您的反馈。

I'm currently using SOA, I've a bunch of Service, (ArticleService, CommentService, UserService, etc..)

I also have a ConfigurationService which is filled from an XML configuration file.

I'm using Zend Framework.

THis configuration service is needed in some of my service, and I'm using dependency injection, is it a good practice, to add ConfigurationService in constructor of most my Service to be able to fetch global configuration?

Thank you for your feedbacks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

執念 2024-11-22 14:17:21

我想说,不,不要在其他服务的构造函数中传递配置容器 - 既不是作为服务,也不是作为数组,也不是 Zend_Config 实例。我会将这些服务的注入(无论是通过构造函数还是通过设置器)集中在他们实际需要的实际对象/协作者/数据上。

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

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

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

Bootstrap snippet:

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

then the 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 - 也许是 Symfony DIC 或 ZF2 中新的 Zend\Di 包 - 可能会更好。但是,经过几个月的努力,尝试了所有注入依赖项的最佳实践建议,这就是我得出的结论。如果它很愚蠢或者完全错误,请(拜托!)纠正我。 ;-)

I would say, no, don't pass the config container - neither as a service nor as an array nor a Zend_Config instance - in the constructor of your other services. I would keep the injection (whether by constructor or by setter) for those services focused on the actual objects/collaborators/data they actually need.

So, for example, an ArticleService might depend upon an ArticleRepository interface/object or on an ArticleMapper or on a db adapter. Let the constructor/setter signatures for the ArticleService reflect what it truly needs.

Instead, what I would do is during Bootstrap, create some kind of factory object - perhaps as an application resource - that accepts in its constructor your config data/object/service (or even better, the bootstrap instance itself, from which you could get, not just your config data, but also any application resources, like a db adapter, that were created during the bootstrap process). Then write methods on your factory object that create/deliver the other services you need. Internally, the factory maintains a registry of already created services so that it can lazy-create instances where required.

A snippet of what I have in mind might be as follows:

Bootstrap snippet:

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

Then the 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'];
    }
}

Then in a controller, you could grab an ArticleService instance:

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
    }

}

The upshot here is that each service explicitly identifies the collaborators it needs and the factory is a single place that takes care of creating/injecting all those collaborators.

Finally, I confess that I am just spitballing here. To me, this is essentially a rudimentary dependency injection container; in that sense, using a fully-featured DIC - perhaps the Symfony DIC or the new Zend\Di package in ZF2 - might be better. But after many months of struggling with all the best-practice recommendations to inject your dependencies, this is what I have come up with. If it's goofy or just plain wrong, please (please!) straighten me out. ;-)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文