自动定义服务依赖关系(自动装配)

编辑该页面

警告:你浏览的文档欧宝官网下载appob娱乐下载Symfony 4.1,不再维护。

这个页面的更新版本Symfob娱乐下载ony 6.2(当前的稳定版本)。

自动定义服务依赖关系(自动装配)

自动装配允许您管理服务的容器以最小的配置。它读取类型提示你的构造函数(或其他方法),并自动为每个方法传递正确的服务。ob娱乐下载Symfony的自动装配设计是可以预见的:如果不是很清楚哪些依赖应该通过,您将看到一个可操作的例外。

提示

由于Symfony的ob娱乐下载编译后的容器,没有使用自动装配的运行时开销。

一个自动装配的例子

想象一下你正在构建一个API在Twitter发布状态,混淆ROT13一个有趣的编码器,转移所有字符13个字母在字母表。

首先创建一个ROT13变压器类:

1 2 3 4 5 6 7 8 9
名称空间应用程序\跑龙套;Rot13Transformer{公共函数变换(美元价值){返回函数美元价值);}}

现在Twitter客户端使用这个变压器:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
名称空间应用程序\服务;使用应用程序\跑龙套\Rot13Transformer;TwitterClient{私人美元变压器;公共函数__construct(Rot13Transformer美元变压器){美元- >变压器=美元变压器;}公共函数推特(美元用户,美元关键,美元状态){美元transformedStatus=美元- >变压器- >变换(美元状态);/ /……连接到Twitter和发送编码状态}}

如果你使用默认的服务。yaml的配置,两类自动注册为服务和配置为autowired的。这意味着您可以立即使用它们任何配置。

然而,为了更好地理解自动装配,下面的例子明确配置两个服务:

  • YAML
  • XML
  • PHP
1 2 3 4 5 6 7 8 9 10 11 12 13 14
#配置/ services.yaml服务:_defaults:自动装配:真正的可以使用autoconfigure:真正的公众:#……应用程序服务\ \ TwitterClient:#由于_defaults冗余,但价值是重写的每个服务自动装配:真正的App \ Util \ Rot13Transformer:自动装配:真正的

现在,您可以使用TwitterClient服务立即控制器:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
名称空间应用程序\控制器;使用应用程序\服务\TwitterClient;使用ob娱乐下载\\FrameworkBundle\控制器\AbstractController;使用ob娱乐下载\组件\路由\注释\路线;DefaultController扩展AbstractController{/ * * *@Route(“/推”,方法= {“POST”}) * /公共函数推特(TwitterClient美元twitterClient){/ /获取用户,美元,美元地位的“POST”数据美元twitterClient- >推特(美元用户,美元关键,美元状态);/ /……}}

这是自动!容器知道通过Rot13Transformer当创建服务作为第一个参数TwitterClient服务。

自动装配逻辑解释

自动装配是通过读取Rot13Transformertype-hintTwitterClient:

1 2 3 4 5 6 7 8 9 10 11 12
/ /……使用应用程序\跑龙套\Rot13Transformer;TwitterClient{/ /……公共函数__construct(Rot13Transformer美元变压器){美元- >变压器=美元变压器;}}

自动装配系统寻找一个服务其id type-hint完全匹配:所以App \ Util \ Rot13Transformer。在这种情况下,存在!当您配置Rot13Transformer服务,您使用它的完全限定类名作为其id。自动装配并不是魔法:它只是查找服务id和type-hint相匹配的。如果你负载自动服务,每个服务的id是它的类名。

如果有服务id完全匹配的类型,将会抛出一个清晰异常。

自动装配是一个伟大的方式来自动配置和Symfony试图一样ob娱乐下载可预测的尽可能的和明确的。

使用别名来实现自动装配

配置自动装配的主要方式是创建一个id完全匹配它的类的服务。在前面的示例中,服务的idApp \ Util \ Rot13Transformer自动,它允许我们自动装配这种类型。

这也可以使用一个完成别名。假设由于某种原因,服务的idapp.rot13.transformer。在这种情况下,任何参数type-hinted类名(App \ Util \ Rot13Transformer)可以不再autowired的。

没问题!为了解决这个问题,你可以创建服务的id匹配的类添加一个服务别名:

  • YAML
  • XML
  • PHP
1 2 3 4 5 6 7 8 9 10 11 12 13
#配置/ services.yaml服务:#……# id不是一个类,所以它不会被用于自动装配app.rot13.transformer:类:App \ Util \ Rot13Transformer#……#但这修复它!#“app.rot13。变压器`` service will be injected when< /span>#一个“应用程序\ Util \ Rot13Transformer“type-hint检测App \ Util \ Rot13Transformer:“@app.rot13.transformer”

这将创建一个服务“别名”,其idApp \ Util \ Rot13Transformer。谢谢,自动装配认为这和使用它Rot13Transformer类是type-hinted。

提示

所使用的别名是autowired的核心包允许服务。例如,MonologBundle创建一个服务的id日志记录器。但它也添加别名:Psr \ \ LoggerInterface日志指向日志记录器服务。这就是为什么参数type-hintedPsr \ \ LoggerInterface日志可以autowired的。

使用接口

你也可能发现自己类型提示抽象(如接口),而不是具体的类,因为它很容易取代你与其他对象的依赖关系。

遵循这些最佳实践,假设你决定创建一个TransformerInterface:

1 2 3 4 5 6
名称空间应用程序\跑龙套;接口TransformerInterface{公共函数变换(美元价值);}

然后,你更新Rot13Transformer实现它:

1 2 3 4 5
/ /……Rot13Transformer实现了TransformerInterface{/ /……}

现在你有一个接口,您应该使用这个作为type-hint:

1 2 3 4 5 6 7 8 9
TwitterClient{公共函数__construct(TransformerInterface美元变压器){/ /……}/ /……}

但是现在,type-hint (App \ Util \ TransformerInterface)不再匹配的id服务(App \ Util \ Rot13Transformer)。这意味着不再autowired的论证。

为了解决这个问题,添加一个别名:

  • YAML
  • XML
  • PHP
1 2 3 4 5 6 7 8 9
#配置/ services.yaml服务:#……App \ Util \ Rot13Transformer:~#“App \ Util \ Rot13Transformer“服务时将被注入#一个“应用程序\ Util \ TransformerInterface“type-hint检测App \ Util \ TransformerInterface:“@App \ Util \ Rot13Transformer”

多亏了App \ Util \ TransformerInterface别名,自动装配子系统知道App \ Util \ Rot13Transformer服务应该被注入在处理TransformerInterface

提示

当使用一个服务定义原型发现,如果只有一个服务实现一个接口,该接口也同时发现,配置别名不是强制性的,Symfony会自动创建一个。ob娱乐下载

处理多个相同类型的实现

假设您创建第二个类-UppercaseTransformer实现TransformerInterface:

1 2 3 4 5 6 7 8 9
名称空间应用程序\跑龙套;UppercaseTransformer实现了TransformerInterface{公共函数变换(美元价值){返回strtoupper (美元价值);}}

如果你注册这个服务,你现在有了两个服务实现App \ Util \ TransformerInterface类型。自动装配子系统不能决定使用哪一个。记住,自动装配不是魔法;它只是看起来服务id和type-hint相匹配的。所以你需要选择一个类型的通过创建一个别名(见正确的服务id自动定义服务依赖关系(自动装配))。

如果你想要Rot13Transformer用于自动装配的服务,创建别名:

  • YAML
  • XML
  • PHP
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
#配置/ services.yaml服务:#……App \ Util \ Rot13Transformer:~App \ Util \ UppercaseTransformer:~#“App \ Util \ Rot13Transformer“服务时将被注入#“应用\ Util \ TransformerInterface“type-hint检测App \ Util \ TransformerInterface:“@App \ Util \ Rot13Transformer”应用程序服务\ \ TwitterClient:# Rot13Transformer将作为美元的变压器参数传递自动装配:真正的#如果你想选择非默认服务,手动线#参数:# $变压器:“@App \ Util \ UppercaseTransformer”#……

多亏了App \ Util \ TransformerInterface别名,任何争论type-hinted与此接口将被通过了App \ Util \ Rot13Transformer服务。但是,你也可以手动线其他服务通过指定参数下的参数键。

修复Non-Autowireable参数

是一个自动装配只能当你的论点对象。但是如果你有一个标量参数(如字符串),这不能autowired: Symfony将抛出一个清晰异常。ob娱乐下载

为了解决这个问题,你可以手动线有问题的争论。你线困难的争论,Symfony照顾休息。ob娱乐下载

自动装配其他方法(例如setter)

当启用了自动装配的服务时,你可以配置容器调用在你的类的实例化方法。例如,假设您想注入日志记录器服务,并决定使用setter注入:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
名称空间应用程序\跑龙套;Rot13Transformer{私人美元日志记录器;/ * * *@ required* /公共函数setLogger(LoggerInterface美元日志记录器){美元- >记录器=美元日志记录器;}公共函数变换(美元价值){美元- >日志记录器- >信息(“改变”美元价值);/ /……}}

自动装配会自动调用任何方法与@ required每个参数注释上面,自动装配。如果你需要手动线的一些参数的方法,你可以明确配置方法调用

自动装配控制器动作方法

如果你使用Symfony框架,你还可以自ob娱乐下载动装配参数控制器动作的方法。这是自动装配的特殊情况,为了方便存在。看到控制器为更多的细节。

性能的影响

由于Symfony的ob娱乐下载容器,编译没有使用自动装配的性能损失。然而,有一个小的性能损失dev环境,尽可能经常容器可能重建修改类。如果重建你的容器是缓慢(可能非常大的项目),你可能无法使用自动装配。

公众和可重用的包

公共bundle应该显式配置其服务,而不是依靠自动装配。

这项工作,包括代码示例,许可下Creative Commons冲锋队3.0许可证。