理解PHP依赖注入容器(dependency injection container)系列(四) Symfony服务容器:利用Builder创建服务
2016-09-25 10:55
1161 查看
上篇讲述了利用继承sfServiceContainer类,为容器提供简单易用的接口调用。接下来我们会讲到如何进一步利用sfServiceContainerBuilder 类描述服务和配置。
sfServiceContainerBuilder是继承sfServiceContainer类的(每一个容器类如sfServiceContainer类都实现了sfServiceContainerInterface接口),它使开发者可以通过一种简洁易用的方式来描述服务。
服务的描述是通过注册服务定义完成的。每个服务定义描述了一个服务:从使用构造函数传递参数的类,和一堆其他的配置属性(见下面的sfservicedefinition边栏)
再回到Zend_Mail这个例子,现在我们要把其中的硬编码去除掉,并利用builder类动态创建它
通过register()方法我们完成了对服务的创建。只需要给出service name和class name,该方法返回sfServiceDefinition实例。
服务定义在内部是通过sfservicedefinition对像实现的。也可以手工创建,再直接利用容器的setservicedefinition()方法登记。
sfServiceDefinition对像实现了一个接口并且提供了几个能对服务进行配置的方法,在上面的例子中,我们使用了这几个方法:
addArgument():给服务的构造函数传递一个参数。
setShared():在当前容器中,该服务是否唯一(默认情况下为true)
addMethodCall():设置服务被创建后触发的委托事件。第一个参数是要委托调用的方法,第二个参数是向方法传递的参数数组
sfServiceDefinition 的相关方法:
setConstructor():设置创建服务时使用的静态方法,用来替换标准的new __construct方式(一般用在对像工厂)
setClass:设置服务类
setArguments(): 为构造函数设置多个参数(顺序很关键)
addArgument(): 为构造函数设置一个参数
setMethodCalls():设置服务被创建后触发的委托事件方法簇,按造顺序执行。
addMethodCall():设置服务被创建后触发的委托事件,允许多次添加同一个方法。
setFile(): 设置一个文件包含路径,该文件将在创建服务前被引用include(在服务没有实现自动加载文件时有用)
setShared():在当前容器中,该服务是否唯一(默认情况下为true)
setConfigurator():设置委托方法,在服务配置完成后调用。
现在引用一个服务是通过实例化sfServiceReference类来实现的(如:new sfServiceReference(‘mail.transport’) .)。这个特殊的类可以根据参数动态的创建服务。
在注册过程中,服务并没有真正被创建,仅仅是描述了如何获取并配置该服务。只有在真正使用服务时,服务才会被实例化。这就是说,你可以在任何顺序任何位置创建注册你的服务,而不用担心服务依赖的对像是否在它之前注册。这也意味着后面注册的服务如果名字相同,则可以覆盖前面的服务。在测试时,需要重写一些方法时这不失为一个好的办法。
sfServiceContainerBuilder类实现了标准sfServiceContainerInterface接口。来看一下接口定义:
我们使用容器可以不用改变代码:
sfServiceContainerBuilder 可以描述如何实例化、配置对像。上面的Zend_Mail例子已经展示了这一切,现在我们看另一个来源于Symfony的例子,这个例子用到了sfUser类:
容器参数的存储对像是通过数组传递的时侯,如果我们要使用某个参数,就要用到占位符(addArgument(‘%storage.options%’))
下一篇将介绍如何用 XML or YAML文件描述服务。
sfServiceContainerBuilder是继承sfServiceContainer类的(每一个容器类如sfServiceContainer类都实现了sfServiceContainerInterface接口),它使开发者可以通过一种简洁易用的方式来描述服务。
服务的描述是通过注册服务定义完成的。每个服务定义描述了一个服务:从使用构造函数传递参数的类,和一堆其他的配置属性(见下面的sfservicedefinition边栏)
再回到Zend_Mail这个例子,现在我们要把其中的硬编码去除掉,并利用builder类动态创建它
require_once 'PATH/TO/sf/lib/sfServiceContainerAutoloader.php'; sfServiceContainerAutoloader::register(); $sc = new sfServiceContainerBuilder(); $sc-> register('mail.transport', 'Zend_Mail_Transport_Smtp')-> addArgument('smtp.gmail.com')-> addArgument(array( 'auth' => 'login', 'username' => '%mailer.username%', 'password' => '%mailer.password%', 'ssl' => 'ssl', 'port' => 465, ))-> setShared(false) ; $sc-> register('mailer', '%mailer.class%')-> addMethodCall('setDefaultTransport', array(new sfServiceReference('mail.transport'))) ;
通过register()方法我们完成了对服务的创建。只需要给出service name和class name,该方法返回sfServiceDefinition实例。
服务定义在内部是通过sfservicedefinition对像实现的。也可以手工创建,再直接利用容器的setservicedefinition()方法登记。
sfServiceDefinition对像实现了一个接口并且提供了几个能对服务进行配置的方法,在上面的例子中,我们使用了这几个方法:
addArgument():给服务的构造函数传递一个参数。
setShared():在当前容器中,该服务是否唯一(默认情况下为true)
addMethodCall():设置服务被创建后触发的委托事件。第一个参数是要委托调用的方法,第二个参数是向方法传递的参数数组
sfServiceDefinition 的相关方法:
setConstructor():设置创建服务时使用的静态方法,用来替换标准的new __construct方式(一般用在对像工厂)
setClass:设置服务类
setArguments(): 为构造函数设置多个参数(顺序很关键)
addArgument(): 为构造函数设置一个参数
setMethodCalls():设置服务被创建后触发的委托事件方法簇,按造顺序执行。
addMethodCall():设置服务被创建后触发的委托事件,允许多次添加同一个方法。
setFile(): 设置一个文件包含路径,该文件将在创建服务前被引用include(在服务没有实现自动加载文件时有用)
setShared():在当前容器中,该服务是否唯一(默认情况下为true)
setConfigurator():设置委托方法,在服务配置完成后调用。
现在引用一个服务是通过实例化sfServiceReference类来实现的(如:new sfServiceReference(‘mail.transport’) .)。这个特殊的类可以根据参数动态的创建服务。
在注册过程中,服务并没有真正被创建,仅仅是描述了如何获取并配置该服务。只有在真正使用服务时,服务才会被实例化。这就是说,你可以在任何顺序任何位置创建注册你的服务,而不用担心服务依赖的对像是否在它之前注册。这也意味着后面注册的服务如果名字相同,则可以覆盖前面的服务。在测试时,需要重写一些方法时这不失为一个好的办法。
sfServiceContainerBuilder类实现了标准sfServiceContainerInterface接口。来看一下接口定义:
interface sfServiceContainerInterface { public function setParameters(array $parameters); public function addParameters(array $parameters); public function getParameters(); public function getParameter($name); public function setParameter($name, $value); public function hasParameter($name); public function setService($id, $service); public function getService($id); public function hasService($name); }
我们使用容器可以不用改变代码:
$sc->addParameters(array( 'mailer.username' => 'foo', 'mailer.password' => 'bar', 'mailer.class' => 'Zend_Mail', )); $mailer = $sc->mailer;
sfServiceContainerBuilder 可以描述如何实例化、配置对像。上面的Zend_Mail例子已经展示了这一切,现在我们看另一个来源于Symfony的例子,这个例子用到了sfUser类:
$sc = new sfServiceContainerBuilder(array( 'storage.class' => 'sfMySQLSessionStorage', 'storage.options' => array('database' => 'session', 'db_table' => 'session'), 'user.class' => 'sfUser', 'user.default_culture' => 'en', )); $sc->register('dispatcher', 'sfEventDispatcher'); $sc-> register('storage', '%storage.class%')-> addArgument('%storage.options%') ; $sc-> register('user', '%user.class%')-> addArgument(new sfServiceReference('dispatcher'))-> addArgument(new sfServiceReference('storage'))-> addArgument(array('default_culture' => '%user.default_culture%'))-> ; $user = $sc->user;
容器参数的存储对像是通过数组传递的时侯,如果我们要使用某个参数,就要用到占位符(addArgument(‘%storage.options%’))
下一篇将介绍如何用 XML or YAML文件描述服务。
相关文章推荐
- 理解PHP依赖注入容器(dependency injection container)系列(三) Symfony服务容器介绍
- 理解PHP依赖注入容器(dependency injection container)系列(六)Symfony服务容器:速度至上
- 理解PHP依赖注入容器(dependency injection container)系列(五) 使用XML 或 YAML 来描述服务
- 理解PHP依赖注入容器(dependency injection container)系列(二) 你需要依赖注入容器吗?
- 理解PHP依赖注入容器(dependency injection container)系列(一) 什么是依赖注入
- PHP程序员如何理解依赖注入容器(dependency injection container)
- php 依赖注入容器(dependency injection container)
- php 依赖注入容器(dependency injection container)
- [转] 深度理解依赖注入(Dependence Injection): Inversion of Control Containers and the Dependency Injection pattern
- Laravel 服务容器实例教程 —— 深入理解控制反转(IoC)和依赖注入(DI)
- Laravel 服务容器实例教程 —— 深入理解控制反转(IoC)和依赖注入(DI)
- 创建你自己的依赖注入容器Ioc Container(转)
- laravel服务容器-----深入理解控制反转(IoC)和依赖注入(DI)
- 创建你自己的依赖注入容器Ioc Container
- Laravel 服务容器实例教程 —— 深入理解控制反转(IoC)和依赖注入(DI)
- Laravel 服务容器实例教程 —— 深入理解控制反转(IoC)和依赖注入(DI)
- 关于laravel 自动加载和依赖注入、服务容器、服务提供者的理解--1
- 依赖注入 控制反转 服务定位器 模式 Dependency Injection Inversion of Control Service Locator Patterns | 超级经典
- Laravel 服务容器实例教程 —— 深入理解控制反转(IoC)和依赖注入(DI)
- 理解PHP 依赖注入|Laravel IoC容器