福建网站开发公司,国内产品设计网站,ih5网页设计,曲靖网站微信建设IoC 主题 1.容器概述2. bean 概述3.依赖注入 (DI)4.Bean 的范围5.定制一个bean Spring 框架最重要的是控制反转 (IoC) 容器 1.容器概述
org.springframework.context.ApplicationContext 接口代表 Spring IoC 容器#xff0c;负责实例化、配置和组装 bean。 容器通过读取配置… IoC 主题 1.容器概述2. bean 概述3.依赖注入 (DI)4.Bean 的范围5.定制一个bean Spring 框架最重要的是控制反转 (IoC) 容器 1.容器概述
org.springframework.context.ApplicationContext 接口代表 Spring IoC 容器负责实例化、配置和组装 bean。 容器通过读取配置元数据来获取要实例化、配置和组装哪些对象的指令。 配置元数据以 XML、Java 注释或 Java 代码表示。 它可以让您表达组成应用程序的对象以及这些对象之间丰富的相互依赖性。
Spring 提供了 ApplicationContext 接口的多个实现。 在独立应用程序中通常创建 ClassPathXmlApplicationContext 或 FileSystemXmlApplicationContext 的实例。 虽然 XML 是定义配置元数据的传统格式但您可以通过提供少量 XML 配置来指示容器使用 Java 注释或代码作为元数据格式以声明方式启用对这些附加元数据格式的支持。
在大多数应用场景中不需要显式的用户代码来实例化一个或多个 Spring IoC 容器实例。 例如在 Web 应用程序场景中应用程序的 web.xml 文件中的简单八行左右样板 Web 描述符 XML 通常就足够了请参阅 Web 应用程序的便捷 ApplicationContext 实例化。
下图显示了 Spring 工作原理的高级视图。 您的应用程序类与配置元数据相结合以便在创建并初始化 ApplicationContext 后您拥有一个完全配置且可执行的系统或应用程序。
2. bean 概述
Spring IoC 容器管理一个或多个 bean。 这些 bean 是使用您提供给容器的配置元数据创建的例如以 XML 定义的形式。
在容器本身内这些 bean 定义表示为 BeanDefinition 对象其中包含以及其他信息以下元数据 包限定的类名通常是所定义的 bean 的实际实现类。 Bean 行为配置元素说明 Bean 在容器中的行为方式范围、生命周期回调等。 对 Bean 完成其工作所需的其他 Bean 的引用。 这些引用也称为协作者或依赖项。 在新创建的对象中设置的其他配置设置——例如池的大小限制或管理连接池的 bean 中使用的连接数。
此元数据转换为构成每个 bean 定义的一组属性。 下表描述了这些属性
属性说明ClassInstantiating BeansNameNaming BeansScopeBean ScopesConstructor argumentsDependency InjectionPropertiesDependency InjectionAutowiring modeAutowiring CollaboratorsLazy initialization modeLazy-initialized BeansInitialization methodInitialization CallbacksDestruction methodDestruction Callbacks
NOTE:
ApplicationContext 实现还允许注册在容器外部由用户创建的现有对象。 这是通过 getBeanFactory() 方法访问 ApplicationContext 的 BeanFactory 来完成的该方法返回 BeanFactory DefaultListableBeanFactory 实现。 DefaultListableBeanFactory 通过 registerSingleton(…) 和 registerBeanDefinition(…) 方法支持这种注册。 然而典型的应用程序仅使用通过常规 bean 定义元数据定义的 bean。
Bean 元数据和手动提供的单例实例需要尽早注册以便容器在自动装配和其他自省步骤期间正确推理它们。 虽然在某种程度上支持覆盖现有元数据和现有单例实例但官方不支持在运行时注册新 bean与对工厂的实时访问同时进行并且可能会导致并发访问异常、bean 容器中的状态不一致。
3.依赖注入 (DI)
依赖注入 (DI) 是一个过程对象仅通过构造函数参数、工厂方法的参数或对象实例构造后设置的属性来定义其依赖项即与它们一起工作的其他对象。 从工厂方法返回。 然后容器在创建 bean 时注入这些依赖项。 这个过程从根本上来说是 bean 本身的逆过程因此得名“控制反转”通过使用类的直接构造或服务定位器模式自行控制其依赖项的实例化或位置。
采用 DI 原则代码更加清晰并且当对象提供其依赖项时解耦更加有效。 该对象不会查找其依赖项也不知道依赖项的位置或类。 因此您的类变得更容易测试特别是当依赖项位于接口或抽象基类上时这允许在单元测试中使用存根或模拟实现。
DI 存在两种主要变体基于构造函数的依赖注入和基于 Setter 的依赖注入。
基于构造函数的依赖注入
基于构造函数的 DI 是通过容器调用带有多个参数的构造函数来完成的每个参数代表一个依赖项。 使用特定参数调用静态工厂方法来构造 bean 几乎是等效的并且本讨论以类似方式对待构造函数和静态工厂方法的参数。 以下示例显示了一个只能通过构造函数注入进行依赖注入的类
构造函数参数解析
构造函数参数解析匹配通过使用参数的类型进行。 如果 bean 定义的构造函数参数中不存在潜在的歧义则在 bean 定义中定义构造函数参数的顺序就是在实例化 bean 时将这些参数提供给适当的构造函数的顺序。 考虑下面的类
public class ExampleBean {// Number of years to calculate the Ultimate Answerprivate final int years;// The Answer to Life, the Universe, and Everythingprivate final String ultimateAnswer;public ExampleBean(int years, String ultimateAnswer) {this.years years;this.ultimateAnswer ultimateAnswer;}
}依赖解析过程
容器执行bean依赖解析如下
ApplicationContext 使用描述所有 bean 的配置元数据创建和初始化。 配置元数据可以通过 XML、Java 代码或注释来指定。
对于每个 bean其依赖项以属性、构造函数参数或静态工厂方法的参数如果您使用它而不是普通构造函数的形式表示。 这些依赖关系是在实际创建 bean 时提供给 bean 的。
每个属性或构造函数参数都是要设置的值的实际定义或对容器中另一个 bean 的引用。
作为值的每个属性或构造函数参数都会从其指定格式转换为该属性或构造函数参数的实际类型。 默认情况下Spring 可以将以字符串格式提供的值转换为所有内置类型例如 int、long、String、boolean 等。
Spring 容器在创建容器时验证每个 bean 的配置。 但是直到实际创建 bean 后才会设置 bean 属性本身。 单例范围并设置为预实例化默认的 Bean 是在创建容器时创建的。 范围在 Bean 范围中定义。 否则仅当请求时才创建 bean。 创建 Bean 可能会导致创建 Bean 图表因为创建并分配了 Bean 的依赖项及其依赖项的依赖项等等。 请注意解析
循环依赖
如果主要使用构造函数注入则可能会创建无法解析的循环依赖场景。
例如A类通过构造函数注入需要B类的实例B类通过构造函数注入需要A类的实例。 如果您为类 A 和 B 配置 Bean 以相互注入Spring IoC 容器会在运行时检测到此循环引用并抛出 BeanCurrentlyInCreationException。
一种可能的解决方案是编辑某些类的源代码使其由 setter 而不是构造函数进行配置。 或者避免构造函数注入并仅使用 setter 注入。 换句话说虽然不推荐但是可以通过setter注入来配置循环依赖。
与典型情况没有循环依赖不同bean A 和 bean B 之间的循环依赖会强制其中一个 Bean 在完全初始化之前注入另一个 Bean典型的先有鸡还是先有蛋的场景。
4.Bean 的范围
创建 bean 定义时您将创建一个配方来创建由该 bean 定义定义的类的实际实例。 bean 定义是一个配方的想法很重要因为这意味着与类一样您可以从单个配方创建许多对象实例。
您不仅可以控制要插入从特定 bean 定义创建的对象中的各种依赖项和配置值还可以控制从特定 bean 定义创建的对象的范围。 这种方法功能强大且灵活因为您可以通过配置选择创建的对象的范围而不必在 Java 类级别烘焙对象的范围。 Bean 可以定义为部署在多个范围之一中。 Spring 框架支持六个作用域其中四个作用域仅在您使用 Web 感知的 ApplicationContext 时才可用。 您还可以创建自定义范围。
下表描述了支持的范围 单例 默认将单个 bean 定义范围限定为每个 Spring IoC 容器的单个对象实例。 原型 将单个 bean 定义的范围限定为任意数量的对象实例。 请求request 将单个 bean 定义的范围限定为单个 HTTP 请求的生命周期。 也就是说每个 HTTP 请求都有自己的 Bean 实例该实例是根据单个 Bean 定义创建的。 仅在 Web 感知的 Spring ApplicationContext 上下文中有效。 会话 session 将单个 bean 定义的范围限定为 HTTP 会话的生命周期。 仅在 Web 感知的 Spring ApplicationContext 上下文中有效。 应用 application 将单个 bean 定义的范围限定为 ServletContext 的生命周期。 仅在 Web 感知的 Spring ApplicationContext 上下文中有效。 网络套接字 将单个 bean 定义的范围限定为 WebSocket 的生命周期。 仅在 Web 感知的 Spring ApplicationContext 上下文中有效。
5.定制一个bean 生命周期回调 Callbacks ApplicationContextAware 和 BeanNameAware
要与容器对 bean 生命周期的管理进行交互您可以实现 Spring 的 InitializingBean 和 DisposableBean 接口。 容器为前者调用 afterPropertiesSet() 为后者调用 destroy() 让 Bean 在初始化和销毁 Bean 时执行某些操作。
JSR-250 PostConstruct 和 PreDestroy 注释通常被认为是在现代 Spring 应用程序中接收生命周期回调的最佳实践。 使用这些注释意味着您的 bean 不会耦合到 Spring 特定的接口。 有关详细信息请参阅使用PostConstruct 和PreDestroy。
如果您不想使用 JSR-250 注释但仍想消除耦合请考虑 init-method 和 destroy-method bean 定义元数据。
在内部Spring 框架使用 BeanPostProcessor 实现来处理它可以找到的任何回调接口并调用适当的方法。 如果您需要 Spring 默认情况下未提供的自定义功能或其他生命周期行为您可以自己实现 BeanPostProcessor。 有关更多信息请参阅容器扩展点。
除了初始化和销毁回调之外Spring 管理的对象还可以实现 Lifecycle 接口以便这些对象可以参与容器自身生命周期驱动的启动和关闭过程。
初始化回调
org.springframework.beans.factory.InitializingBean 接口允许 bean 在容器设置 bean 的所有必要属性后执行初始化工作。 InitializingBean 接口指定了一个方法 void afterPropertiesSet() throws Exception;销毁回调
实现 org.springframework.beans.factory.DisposableBean 接口可以让 bean 在包含它的容器被销毁时获得回调。 DisposableBean 接口指定了一个方法 void destroy() throws Exception;