注入类型

编辑本页

注入类型

使类的依赖关系显式化,并要求将它们注入到类中,这是使类更具可重用性、可测试性和与其他类解耦的好方法。

有几种方法可以注入依赖项。在使用服务容器时,每个注入点都有其优缺点,以及使用它们的不同方式。

构造函数注入

注入依赖关系最常见的方法是通过类的构造函数。要做到这一点,你需要在构造函数签名中添加一个参数来接受依赖:

12 3 4 5 6 7 8 9 10 11 12 13 14 15
/ / src /邮件/欧宝app在哪里找 NewsletterManager.php名称空间应用程序邮件/ /……欧宝app在哪里找NewsletterManager私人梅勒公共函数__construct(MailerInterface梅勒->梅勒=梅勒;}/ /……

你可以在服务容器配置中指定你想要注入什么服务:

  • YAML
  • XML
  • PHP
1 2 3 4 5 6
#配置/ services.yaml服务:#……邮件\ App \欧宝app在哪里找 NewsletterManager:参数:(“@mailer”)

提示

类型提示注入的对象意味着您可以确定已经注入了合适的依赖项。通过类型提示,如果注入了不合适的依赖项,您将立即得到一个明确的错误。通过使用接口而不是类的类型提示,可以使依赖项的选择更加灵活。并且假设您只使用接口中定义的方法,您可以获得这种灵活性,并且仍然可以安全地使用对象。

使用构造函数注入有几个优点:

  • 如果依赖项是一种需求,类没有依赖项就不能工作,那么通过构造函数注入依赖项可以确保在使用类时存在依赖项,因为没有依赖项就不能构造类。
  • 在创建对象时,构造函数只被调用一次,因此可以确保依赖关系在对象的生命周期内不会改变。

这些优点确实意味着构造函数注入不适合使用可选依赖项。与类层次结构结合使用也更加困难:如果一个类使用构造函数注入,那么扩展它和重写构造函数就会成为问题。

Immutable-setter注入

另一种可能的注入是使用一个方法,通过克隆原始服务返回一个单独的实例,这种方法允许你使服务不可变:

12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
/ / src /邮件/欧宝app在哪里找 NewsletterManager.php名称空间应用程序邮件/ /……使用欧宝娱乐app下载地址组件梅勒MailerInterface欧宝app在哪里找NewsletterManager私人梅勒/ * * *@ required@return静态* /公共函数withMailer(MailerInterface梅勒自我克隆->梅勒=梅勒返回;}/ /……

为了使用这种类型的注入,不要忘记配置它:

  • YAML
  • XML
  • PHP
1 2 3 4 5 6 7 8
#配置/ services.yaml服务:#……app.欧宝app在哪里找newsletter_manager:类:应用\ \ New欧宝app在哪里找sletterManager邮件电话:-withMailer:returns_clone !(“@mailer”)

请注意

如果决定使用自动装配,这种类型的注入需要添加@return静态以便容器能够注册该方法。

如果你需要根据需要配置你的服务,这种方法是有用的,所以,以下是不可变设置器的优点:

  • 不可变setter与可选依赖项一起工作,这样,如果你不需要依赖项,就不需要调用setter。
  • 与构造函数注入一样,使用不可变setter强制依赖项在服务的生命周期内保持不变。
  • 这种类型的注入与trait配合得很好,因为可以组合服务,这样使服务更容易适应您的应用程序需求。
  • 可以多次调用setter,通过这种方式,向集合添加依赖项变得更容易,并允许您添加数量可变的依赖项。

缺点是:

  • 由于setter调用是可选的,因此在调用服务的方法时依赖项可以为空。在使用该依赖项之前,必须检查该依赖项是否可用。
  • 除非将服务声明为lazy,否则它与在所谓的循环中相互引用的服务不兼容。

Setter注入

另一个可能的类注入点是通过添加一个接受依赖的setter方法:

12 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/ / src /邮件/欧宝app在哪里找 NewsletterManager.php名称空间应用程序邮件/ /……欧宝app在哪里找NewsletterManager私人梅勒/ * * *@ required* /公共函数setMailer(MailerInterface梅勒无效->梅勒=梅勒;}/ /……
  • YAML
  • XML
  • PHP
1 2 3 4 5 6 7 8
#配置/ services.yaml服务:#……app.欧宝app在哪里找newsletter_manager:类:应用\ \ New欧宝app在哪里找sletterManager邮件电话:-setMailer:(“@mailer”)

这次的优势是:

  • Setter注入在可选依赖项下工作得很好。如果不需要依赖项,则不要调用setter。
  • 您可以多次调用setter。如果该方法将依赖项添加到集合,这将特别有用。然后,您可以拥有数量可变的依赖项。
  • 像不可变setter一样,这种类型的注入与trait一起工作得很好,并允许你组合你的服务。

setter注入的缺点有:

  • setter可以被调用多次,也可以在初始化后很长时间被调用,因此不能确保在对象的生命周期内依赖项没有被替换(除非显式地编写setter方法来检查它是否已经被调用)。
  • 您无法确定将调用setter,因此需要添加检查,以确保注入了所需的依赖项。

属性注入

另一种可能是直接设置类的公共字段:

1 2 3 4 5 6 7
/ /……欧宝app在哪里找NewsletterManager公共梅勒/ /……
  • YAML
  • XML
  • PHP
1 2 3 4 5 6 7 8
#配置/ services.yaml服务:#……app.欧宝app在哪里找newsletter_manager:类:应用\ \ New欧宝app在哪里找sletterManager邮件属性:梅勒:“@mailer”

使用属性注入主要只有缺点,它类似于setter注入,但有这些额外的重要问题:

  • 你根本无法控制何时设置依赖项,它可以在对象生命周期中的任何时候被更改。
  • 不能使用类型提示,因此不能确定注入了什么依赖项,除非在使用类实例之前将其写入类代码显式测试。

但是,知道这可以用服务容器来完成是很有用的,特别是如果您正在处理不受您控制的代码,例如在第三方库中,它使用公共属性作为其依赖项。

此工作,包括代码示例,是根据创作共用BY-SA 3.0许可证。
欧宝娱乐app下载地址Symfony 5.4支持通过私人Packagist