转载

Java程序员必须掌握的Spring依赖管理原理

依赖注入( Dependency Injection )的意思就是对象通过构造器函数参数,工厂方法的参数,或者成员属性,定义了对象的依赖对象;容器在创建该对象时会负责注入这些依赖。这个过程是控制反转的,即不是由即将创建的对象来管理自己的依赖的发现和实例化,而是有Spring容器来实现。

Spring 中依赖注入有两种形式,第一种就是基于构造函数的注入,即通过调用构造函数,传入参数,也就是依赖来完成整个依赖注入流程;第二种就是基于 setter 方法的注入。

构造函数的参数的匹配,要避免歧义,如指定类型,指定参数的次序等。如果是按照参数名字匹配,则必须开启 debug 模式进行编译,否则参数名字是不保留的。如果不想开启 debug 模式编译,则可以使用 @ConstructorProperties 注解。

setter 方法注入是先调用没有参数的默认构造函数构建对象,或者没有参数的静态工厂方法,实例化 bean 后,调用 setter 方法来将该对象注入。

通过使用依赖注入,可以使代码更简洁,更好地实现对象之间解耦。另外,通过依赖注入管理的的对象是 POJO 类,可以更好地进行测试。

如何选择合适的依赖注入方法?

最佳实践是通过构造器方法注入主要依赖对象,通过 setter 方法注入可选的依赖对象。虽然可以在 setter 方法上加上 @Required 注解来实现主要依赖对象注入,但一般还是推荐使用构造器注入必须的依赖。

使用构造器注入,可以使得应用的组件作为不可变的对象,而且可以保证注入依赖是非 null 的。另外,构造器注入返回的是一个完整的初始状态的实例。但是,一般不推荐大量使用构造方法注入,如果出现这种情况,则说明代码需要重构。

setter 方法适合注入可选的依赖,这些依赖可能有默认值,而且在其他位置使用这些依赖时务必要进行 null 值检查。使用 setter 方法的一个好处是可以修改或者重新配置,或者需要时再注入。如基于 JMX MBean 的管理。

Spring依赖解析流程

首先 ApplicationContext 会被创建和初始化,会加载包括描述所有 bean 的元数据。这些配置元数据可以通过 XMLJava 代码或者注解来指定。

对于每一个 bean ,它的依赖表现形式是成员属性,构造器参数,或者静态工厂方法的参数。在 bean 真正创建时, Spring 容器会提供这些依赖的对象。这些参数可能是需要设置的默认值,也可能是另外一个 bean 的引用。

Spring 容器会验证每个 bean 的配置信息。并且在 bean 真正创建时才设置设置属性值或者参数值。

Spring 中,单例作用域的 bean 会提前初始化,在 Spring 容器创建时就进行了实例化。对于其他的作用域的 bean ,则只在需要时才进行创建。之所以单例作用域的 bean 会被提前初始化,主要是为了解决依赖检查的问题,下文的循环依赖一节会详细说明。

Spring 内部会构建一个创建 bean 的依赖图,按照这依赖关系来创建 Bean

循环依赖解决

如果使用构造函数注入,则不能有循环依赖的情况。如 A 构造器依赖 B ,同时 B 也构造器依赖 ASpring IoC 容器会在运行时检测到循环依赖,抛 BeanCurrentlyInCreationException 异常。一种解决办法是通过 setter 方法来解决循环依赖的情况。

Spring 会在容器加载时检测配置问题,如引用不存在或者循环依赖。 Spring 会在必要时才解析依赖,即尽可能晚的来解析依赖关系。延迟解析依赖可能导致后期请求获取对象时报错,如抛出一个异常,如丢失指定对象或者属性。这种配置的延迟的可见性导致的问题使得 ApplicationContext 的实现要求单例作用域的 bean 提前记性初始化。虽然会耗费内存和时间,因为并不是按需创建这些单例作用域的 bean ,但是可以在 ApplicationContext 创建时就可以发现配置问题。

下文会介绍通过指定 bean 的可以通过配置来覆盖默认的行为,使得单例作用域的 bean 也是延迟初始化。

如果没有循环依赖存在,则在注入依赖对象时,这些依赖的对象就已经初始化完成了。即如果 A 依赖 B ,则在 A 初始化时, B 已经初始化完成了。也就是说, Bean 是在相关依赖设置完成,并且相关的生命周期方法调用完毕后,才算是完成了初始化。

bean的延迟初始化

默认情况下 ApplicationContext 是提前初始化单例作用域的 bean ,作为 ApplicationContext 初始化的一部分。这样可以尽快的发现配置问题。可以通过指定 beanlazy-init="true" ,让 bean 在需要时才被初始化。

自动注入依赖

在Spring中可以自动注入依赖,可以减少指定属性或者构造器参数,还可以随着配置对象的变化来更新注入的对象。

自动注入依赖的模式有:通过名称注入,通过类型注入,和通过构造器注入。

原文  https://juejin.im/post/5cb6a65b6fb9a0689f4c2553
正文到此结束
Loading...