依赖注入(Dependency Injection
)的意思就是对象经过构造器函数参数,工厂方法的参数,或者成员属性,定义了对象的依赖对象;容器在建立该对象时会负责注入这些依赖。这个过程是控制反转的,即不是由即将建立的对象来管理本身的依赖的发现和实例化,而是有Spring容器来实现。html
在Spring
中依赖注入有两种形式,第一种就是基于构造函数的注入,即经过调用构造函数,传入参数,也就是依赖来完成整个依赖注入流程;第二种就是基于setter
方法的注入。spring
构造函数的参数的匹配,要避免歧义,如指定类型,指定参数的次序等。若是是按照参数名字匹配,则必须开启debug
模式进行编译,不然参数名字是不保留的。若是不想开启debug
模式编译,则可使用@ConstructorProperties
注解。函数
setter
方法注入是先调用没有参数的默认构造函数构建对象,或者没有参数的静态工厂方法,实例化bean
后,调用setter
方法来将该对象注入。测试
经过使用依赖注入,可使代码更简洁,更好地实现对象之间解耦。另外,经过依赖注入管理的的对象是POJO
类,能够更好地进行测试。ui
最佳实践是经过构造器方法注入主要依赖对象,经过setter
方法注入可选的依赖对象。虽然能够在setter
方法上加上@Required
注解来实现主要依赖对象注入,但通常仍是推荐使用构造器注入必须的依赖。debug
使用构造器注入,可使得应用的组件做为不可变的对象,并且能够保证注入依赖是非null
的。另外,构造器注入返回的是一个完整的初始状态的实例。可是,通常不推荐大量使用构造方法注入,若是出现这种状况,则说明代码须要重构。code
setter
方法适合注入可选的依赖,这些依赖可能有默认值,并且在其余位置使用这些依赖时务必要进行null
值检查。使用setter
方法的一个好处是能够修改或者从新配置,或者须要时再注入。如基于JMX MBean
的管理。htm
首先ApplicationContext
会被建立和初始化,会加载包括描述全部bean
的元数据。这些配置元数据能够经过XML
,Java
代码或者注解来指定。对象
对于每个bean
,它的依赖表现形式是成员属性,构造器参数,或者静态工厂方法的参数。在bean
真正建立时,Spring
容器会提供这些依赖的对象。这些参数多是须要设置的默认值,也多是另一个bean
的引用。生命周期
Spring
容器会验证每一个bean
的配置信息。而且在bean
真正建立时才设置设置属性值或者参数值。
在Spring
中,单例做用域的bean
会提早初始化,在Spring
容器建立时就进行了实例化。对于其余的做用域的bean
,则只在须要时才进行建立。之因此单例做用域的bean
会被提早初始化,主要是为了解决依赖检查的问题,下文的循环依赖一节会详细说明。
在Spring
内部会构建一个建立bean
的依赖图,按照这依赖关系来建立Bean
。
若是使用构造函数注入,则不能有循环依赖的状况。如A
构造器依赖B
,同时B
也构造器依赖A
。Spring IoC
容器会在运行时检测到循环依赖,抛BeanCurrentlyInCreationException
异常。一种解决办法是经过setter
方法来解决循环依赖的状况。
Spring
会在容器加载时检测配置问题,如引用不存在或者循环依赖。Spring
会在必要时才解析依赖,即尽量晚的来解析依赖关系。延迟解析依赖可能致使后期请求获取对象时报错,如抛出一个异常,如丢失指定对象或者属性。这种配置的延迟的可见性致使的问题使得ApplicationContext
的实现要求单例做用域的bean
提早记性初始化。虽然会耗费内存和时间,由于并非按需建立这些单例做用域的bean
,可是能够在ApplicationContext
建立时就能够发现配置问题。
下文会介绍经过指定bean
的能够经过配置来覆盖默认的行为,使得单例做用域的bean
也是延迟初始化。
若是没有循环依赖存在,则在注入依赖对象时,这些依赖的对象就已经初始化完成了。即若是A
依赖B
,则在A
初始化时,B
已经初始化完成了。也就是说,Bean
是在相关依赖设置完成,而且相关的生命周期方法调用完毕后,才算是完成了初始化。
默认状况下ApplicationContext
是提早初始化单例做用域的bean
,做为ApplicationContext
初始化的一部分。这样能够尽快的发现配置问题。能够经过指定bean
的lazy-init="true"
,让bean
在须要时才被初始化。
在Spring中能够自动注入依赖,能够减小指定属性或者构造器参数,还能够随着配置对象的变化来更新注入的对象。
自动注入依赖的模式有:经过名称注入,经过类型注入,和经过构造器注入。
本文总结了Spring
中的依赖管理的基本原理和常见的问题,具体的依赖注入配置语法还须要参考Spring
的官方文档来进行。