如何装饰服务

如何装饰服务

覆盖现有定义时,原始服务丢失:

  • yaml.
    1 2 3 4 5 6 7 8
    #配置/ services.yaml服务app \ mailer.#这将替换旧的app \ mailer定义与新的一个,#旧定义丢失了app \ mailer.班级app \ newmailer.
  • XML
    1 2 3 4 5 6 7 8 9 10 11 12 13 14
    < !——配置/ services . xml——><?XML Version =“1.0”编码=“UTF-8”?><容器XMLNS =.“http://欧宝娱乐app下载地址www.oldmanjams.com/schema/dic/services”XMLNS:XSD =“http://www.w3.org/2001/xmlschema-instance”XSD:Schemalocation =“http://欧宝娱乐app下载地址www.oldmanjams.com/schema/dic/services https://www.oldmanjams.com/schema/dic/services/services-1.0.xsd”><服务><服务ID =“app \ mailer”/><! - 这将替换新的app \ mailer定义与新的一个,旧的定义丢失 - ><服务ID =“app \ mailer”类=“应用程序\ NewMailer”/>> < /容器
  • PHP.
    12 3 4 5 6 7 8 9 10 11 12 13 14 15
    // config / services.php名称空间欧宝娱乐app下载地址Symfony \ Component \ DependencyIngreation \ Loader \ Configurator;app \ mailer.;app \ newmailer.;返回功能containerconfigurator$ Configurator.{美元服务=$ Configurator.- >服务();美元服务- >邮箱::班级);//这将用新的一个替换旧的app \ mailer定义,//旧的定义丢失美元服务- >邮箱::班级NewMailer::班级);};

大多数时候,这正是你想要做的。但有时,您可能想要装饰旧的,而不是(即应用装饰器模式)。在这种情况下,应该保留旧服务,以便能够在新服务中引用它。这个配置替换app \ mailer.有一个新的,但保持旧的一个。内

  • yaml.
    1 2 3 4 5 6 7 8
    #配置/ services.yaml服务app \ mailer.app \ decoratingmailer.#覆盖app \ mailer服务#但该服务仍然是“.inner”装饰app \ mailer.
  • XML
    12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
    < !——配置/ services . xml——><?XML Version =“1.0”编码=“UTF-8”?><容器XMLNS =.“http://欧宝娱乐app下载地址www.oldmanjams.com/schema/dic/services”XMLNS:XSD =“http://www.w3.org/2001/xmlschema-instance”XSD:Schemalocation =“http://欧宝娱乐app下载地址www.oldmanjams.com/schema/dic/services https://www.oldmanjams.com/schema/dic/services/services-1.0.xsd”><服务><服务ID =“app \ mailer”/><! - 覆盖App \ Mailer服务但该服务仍然可用作“.inner” - ><服务ID =“应用程序\ DecoratingMailer”装饰=“app \ mailer”/>> < /容器
  • PHP.
    12 3 4 5 6 7 8 9 10 11 12 13 14 15 16
    // config / services.php名称空间欧宝娱乐app下载地址Symfony \ Component \ DependencyIngreation \ Loader \ Configurator;app \ decoratingmailer.;app \ mailer.;返回功能containerconfigurator$ Configurator.{美元服务=$ Configurator.- >服务();美元服务- >邮箱::班级);美元服务- >DecoratingMailer::班级//重写App邮件服务//,但该服务仍然是“.inner”- >装饰邮箱::班级);};

装饰选项告诉容器app \ decoratingmailer.服务取代了app \ mailer.服务。如果你在用默认服务.YAML配置,当装饰服务的构造函数有一个参数类型时(由装饰服务类暗示),装饰服务将自动注入。

如果不使用Autowiring或装饰服务具有多个构造函数参数类型 - 使用装饰的服务类暗示,则必须明确注入装饰服务(装饰服务的ID自动更改为'。内'):

  • yaml.
    1 2 3 4 5 6 7 8
    #配置/ services.yaml服务app \ mailer.app \ decoratingmailer.装饰app \ mailer.#通过旧服务作为一个论点参数['@。内']
  • XML
    12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
    < !——配置/ services . xml——><?XML Version =“1.0”编码=“UTF-8”?><容器XMLNS =.“http://欧宝娱乐app下载地址www.oldmanjams.com/schema/dic/services”XMLNS:XSD =“http://www.w3.org/2001/xmlschema-instance”XSD:Schemalocation =“http://欧宝娱乐app下载地址www.oldmanjams.com/schema/dic/services https://www.oldmanjams.com/schema/dic/services/services-1.0.xsd”><服务><服务ID =“app \ mailer”/><服务ID =“应用程序\ DecoratingMailer”装饰=“app \ mailer”>< !——传递旧的服务作为参数——><参数类型=“服务”ID =“。内”/>< /服务>> < /容器
  • PHP.
    12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
    // config / services.php名称空间欧宝娱乐app下载地址Symfony \ Component \ DependencyIngreation \ Loader \ Configurator;app \ decoratingmailer.;app \ mailer.;返回功能containerconfigurator$ Configurator.{美元服务=$ Configurator.- >服务();美元服务- >邮箱::班级);美元服务- >DecoratingMailer::班级- >装饰邮箱::班级//传递旧的服务作为参数//在Symfony 5.1之前的版本中,servi欧宝娱乐app下载地址ce()函数被称为ref()- >args.([服务'。内')]);};

5.1新版功能:特殊的。内价值在Symfony 5.1中引入。欧宝娱乐app下载地址在以前的版本中,您需要使用:装饰_service_id.+'。内'

小费

装饰的可见性app \ mailer.服务(新服务的别名)仍然与原始的相同app \ mailer.能见度。

笔记

生成的内部id基于装饰器服务的id (app \ decoratingmailer.这里),而不是装饰服务(app \ mailer.这里)。控件控制内部服务名称decoration_inner_name.选择:

  • yaml.
    1 2 3 4 5 6
    #配置/ services.yaml服务app \ decoratingmailer.#...decoration_inner_name.app \ decoratingmailer.wooz.参数['@app \ decoratingmailer.wooz']
  • XML
    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 17 17 18 19 20
    < !——配置/ services . xml——><?XML Version =“1.0”编码=“UTF-8”?><容器XMLNS =.“http://欧宝娱乐app下载地址www.oldmanjams.com/schema/dic/services”XMLNS:XSD =“http://www.w3.org/2001/xmlschema-instance”XSD:Schemalocation =“http://欧宝娱乐app下载地址www.oldmanjams.com/schema/dic/services https://www.oldmanjams.com/schema/dic/services/services-1.0.xsd”><服务><! -  ...  - ><服务ID =“应用程序\ DecoratingMailer”装饰=“app \ mailer”装饰 - 内部名称=“app \ comentingmailer.wooz”公共=“错误的”><参数类型=“服务”ID =“app \ comentingmailer.wooz”/>< /服务>> < /容器
  • PHP.
    12 3 4 5 6 7 8 9 10 11 12 13 14 15
    // config / services.php名称空间欧宝娱乐app下载地址Symfony \ Component \ DependencyIngreation \ Loader \ Configurator;app \ decoratingmailer.;app \ mailer.;返回功能containerconfigurator$ Configurator.{美元服务=$ Configurator.- >服务();美元服务- >邮箱::班级);美元服务- >DecoratingMailer::班级- >装饰邮箱::班级DecoratingMailer::班级'.wooz'- >args.([服务DecoratingMailer::班级'.wooz')]);};

装饰的优先级

当对一个服务应用多个装饰器时,您可以使用decoration_priority选择。它的值是一个缺省值为的整数0.和更高的优先事项意味着装饰者将在早些时候应用。

  • yaml.
    1 2 3 4 5 6 7 8 9 10 11 12
    #配置/ services.yamlFoo酒吧装饰Foodecoration_priority5.参数['@。内']巴兹装饰Foodecoration_priority1参数['@。内']
  • XML
    1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 17 18 19
    < !——配置/ services . xml——><?XML Version =“1.0”编码=“UTF-8”?><容器XMLNS =.“http://欧宝娱乐app下载地址www.oldmanjams.com/schema/dic/services”XMLNS:XSI =“http://www.w3.org/2001/xmlschema-instance”xsi: schemaLocation =“http://欧宝娱乐app下载地址www.oldmanjams.com/schema/dic/services https://www.oldmanjams.com/schema/dic/services/services-1.0.xsd”><服务><服务ID =“foo”/><服务ID =“酒吧”装饰=“foo”decoration-priority =“5”><参数类型=“服务”ID =“。内”/>< /服务><服务ID =“记者”装饰=“foo”decoration-priority =“1”><参数类型=“服务”ID =“。内”/>< /服务>> < /容器
  • PHP.
    12 3 4 5 6 7 8 9 10 11 12 13 14 15 16
    // config / services.php名称空间欧宝娱乐app下载地址Symfony \ Component \ DependencyIngreation \ Loader \ Configurator;返回功能containerconfigurator$ Configurator.{美元服务=$ Configurator.- >服务();美元服务- >Foo::班级);美元服务- >酒吧::班级- >装饰Foo::班级空值5.- >args.([服务'。内')]);美元服务- >巴兹::班级- >装饰Foo::班级空值1- >args.([服务'。内')]);};

生成的代码如下:

这个美元- >服务[Foo::班级]=新的巴兹新的酒吧新的Foo()));

控制装饰服务不存在时的行为

当您装饰一个不存在的服务时,decoration_on_invalid.选项允许您选择要采用的行为。

有三种不同的行为可用:

  • 例外: 一种ServiceNotFoundException将抛出讲述装饰者的依赖性缺失。(默认)
  • 忽略:容器将移除装饰器。
  • 空值:该容器将保持装饰座服务,并将装饰1空值
  • yaml.
    1 2 3 4 5 6 7
    #配置/ services.yamlFoo酒吧装饰Foodecoration_on_invalid.忽略参数['@。内']
  • XML
    12 3 4 5 6 7 8 9 10 11 12 13 14 15
    < !——配置/ services . xml——><?XML Version =“1.0”编码=“UTF-8”?><容器XMLNS =.“http://欧宝娱乐app下载地址www.oldmanjams.com/schema/dic/services”XMLNS:XSI =“http://www.w3.org/2001/xmlschema-instance”xsi: schemaLocation =“http://欧宝娱乐app下载地址www.oldmanjams.com/schema/dic/services https://www.oldmanjams.com/schema/dic/services/services-1.0.xsd”><服务><服务ID =“foo”/><服务ID =“酒吧”装饰=“foo”装饰无效=“忽略”><参数类型=“服务”ID =“。内”/>< /服务>> < /容器
  • PHP.
    12 3 4 5 6 7 8 9 10 11 12 13 14 15
    // config / services.php名称空间欧宝娱乐app下载地址Symfony \ Component \ DependencyIngreation \ Loader \ Configurator;欧宝娱乐app下载地址symfony \ component \ decigendenceIngress \ containerInterface;返回功能containerconfigurator$ Configurator.{美元服务=$ Configurator.- >服务();美元服务- >Foo::班级);美元服务- >酒吧::班级- >装饰Foo::班级空值0.ContainerInterface::IGNORE_ON_INVALID_REFERENCE- >args.([服务'。内')]);};

谨慎

使用时空值,你可能必须更新装饰器构造函数,以使装饰依赖项为空:

// src / service / decoratorservice.php名称空间App \ Service.;Acme \ OptionalBundle \ \ OptionalService服务;班级DecoratorService.{私人的装饰;公共功能__构造OptionalService装饰{这个美元- >装饰=装饰;}公共功能tellInterestingStuff()字符串{如果!!这个美元- >装饰{返回“只有一件有趣的事”;}返回这个美元- >装饰- >tellInterestingStuff()“+另一件有趣的事”;}}

笔记

有时,您可能希望添加一个编译器传递来动态创建服务定义。如果您想要装饰这样的服务,请确保您的编译器通过已注册passconfig :: type_before_optimization.键入,以便装饰通行证能够找到创建的服务。

这项工作,包括代码样本,是在一个Creative Commons by-SA 3.0执照。