控制反转和依赖注入
IoC 核心是 DI 旨在提供一种更简单的机制来设置组件依赖项,并在整个生命周期中管理这些依赖项 需要某些依赖项的组件通常被称为依赖对象,或者在 IoC 的情况下被称为目标对象 通常, IoC可以分解为两种子类型 依赖注入和依赖查找。
这些子类型被进一步分解为 IoC 服务的 体实现 通过这个定义可以清楚地看到,当谈论 DI 时,通常是在谈论 IoC ,而当谈论 IoC 时,则并不总是在谈论 DI(例如,依赖查找也是 IoC种形式)。
控制反转的类型
- 依赖查找:组件必须获取对依赖项的引用
- 依赖注入:依赖项将通过 IoC 容器注入组件
依赖查找有两种类型 依赖拉取 DL 和上下文依赖查找CDL。
依赖注入 也有两种常见的风格:构造函数和 setter 依赖注入。
依赖拉取
依赖拉取是种最常见的 IoC 类型。
上下文依赖查找
构造函数依赖注入
当在组件的构造函数中提供依赖项时,就会发生构造函数慌攒注人。首先,组件声明一个或一组构造函数,并将其依赖项作为参数,然后在组件实例化时由 IoC 容器将依赖项传递给组件。
setter 依赖注入
setter 依赖注入中, IoC 容器通过 Bean 样式 setter 方法注入组件的依赖工页。组件的 setter 方法公开了 IoC
容器可以管理的依赖项。
Spring中的控制反转
如前所述,控制反转是Spring的重要组成部分。Spring实现的核心是基于依赖注入,尽管也提供了依赖查找功自动将协作者提供给依赖对象时,是使用依赖注入实现的。在基于Spring的应用程序中,始终优先使用依赖注入将协作者传递给依赖对象,而不是让依赖对象通过查找获取协作者。
虽然依赖注入是将协作者和依赖对象连接在一起的首选机制,但有时仍然需要使用依赖查找来访问依赖对象。必须使用依赖查找来访问初始组在许多环境中,Spring无法通过使用依赖注入来自动连接所有应用程序组件,并且
件组。
Spring IoC 容器有个非常有趣的功能,可以在自己的依赖注入容器和外部依赖查询容器之间充当适配器。
Spring 中的依赖注入
Spring 的依赖注入容器的核心是 Beanfactory 接口。
Beanfactory 责管理组件,包括依赖项以及它们的生命周期, 术语 bean用于引用由容器管理的任何组件。
如果应用程序只需要 DI 支持,则可以通过 BeaoFactory 接口与 Spring DI 容器进行交互,这种情况下,应用程
必须创建个实现了 Beanfactory 接口的类的实例,并使用 bean 和依赖信息对其进行配置。
所有这些设置都是自动处理的(例如,在 Web 应用中, Web 容器将在应用程序启动期间通过web.xml描述符文件中声明的 ContextLoaderListener类启动 Spring的ApplicationContext。
bean 配置由实现 BeanDefinition 接口的类的实例表示。
bean 配置不仅存储有关 bean 本身的信息,还存储有关它所依赖的 bean 的信息。
对于任何实现了 BeanDefinitionReader 接口的 Beanfactory 实现类来说,都可以通过使用PropertiesBeanDefinitionReader或XmlBeanDefinitionReader从配置文件中读取BeanDefinition 数据。
PropertiesBeanDefinitionReader 从属性文件读取 bean 定义,而 XmlBeanDefinitionReader则从xml文件中读取相关信息。
BeanFacto 中识别自己的 bean ,为 bean 分配一个 ID、一个名称或两者兼具。一个 bean可以在没有任何 ID或名称的情况下被实例化,或者作为另一个 Bean 的内部bean 被实例化。
每个 bean至少有一个名称,但也可以有任意数量名称,名称用逗号分割。第一个名称后面的任何名称可以认为是同一个 bean的别名 。可以使用 bean ID 或名称从 BeanFactory 检索一个 bean ,并建立依赖关系(也就是说 beanX 赖于 beanY)
ApplicationContextAware
需要访问ApplicationContext,可以实现ApplicationContextAware接口,,它为ApplicationContext对象强制实现一个 setter。Spring IoC 容器会自动进行检测 并且注入 bean 段创建时所在的ApplicationContext。
自动装配
Spring支持五种自动装配模式。
- byName模式:当使用byName模式进行自动装配时,Spring会尝试将每个属性连接到同名的bean。因此,如果目标bean具有名为foo的属性并且在ApplicationContext中定义了foo bean,那么 foo bean将被分配给目标bean的foo属性。
- byType模式:当使用byType进行自动装配时,Spring通过在ApplicationContext中自动使用相同类型的bean来尝试连接目标bean模式的每个属性。
- 构造函数模式:该模式与byType模式在功能上是相同的,只不过使用的是构造函数而不是setter来执行注入。Spring试图匹配构造函数中最大数量的参数。所以,如果bean有两个构造函数,一个接收一个String,另一个接收一个Suring和一个Integer,并且ApplicationContext中有一个String和一个Integer bean,那么 Spring将使用带有两个参数的构造函数。
- 默认模式:Spring将自动在构造函数模式和byType模式之间进行选择。如果bean有一个默认的(无参数)构造函数,那么 Spring使用byType模式;否则,就使用构造函数模式。
- 无:这是默认设置。
当有多个相同Bean时,但是无法选择在哪里使用哪个bean。时有两种方法可以解决这个问题。
第一种方法是,在希望Spring首先考虑自动装配的bean定义中使用primary属性,并将其设置为tue。
另一种解决方案是命名bean并通过XML将它们配置到要注入的地方(这种方法可以完全控制将哪些bean注入到哪里)。
当存在bean相关的类型时,如果能够指定自动装配应按名称完成,那将是非常有用的。想要完成上述操作,需要使用@Qualifier和@Autowired注解,并提供被注入的bean的名称作为参数。