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

Spring依赖注入

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

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

构造函数的参数的匹配,要避免歧义,如指定类型,指定参数的次序等。若是是按照参数名字匹配,则必须开启debug模式进行编译,不然参数名字是不保留的。若是不想开启debug模式编译,则可使用@ConstructorProperties注解
setter方法注入是先调用没有参数的默认构造函数构建对象,或者没有参数的静态工厂方法,实例化bean后,调用setter方法来将该对象注入。并发

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

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

最佳实践是经过构造器方法注入主要依赖对象,经过setter方法注入可选的依赖对象。虽然能够在setter方法上加上@Required注解来实现主要依赖对象注入,但通常仍是推荐使用构造器注入必须的依赖。函数

使用构造器注入,可使得应用的组件做为不可变的对象,并且能够保证注入依赖是非null的。另外,构造器注入返回的是一个完整的初始状态的实例。可是,通常不推荐大量使用构造方法注入,若是出现这种状况,则说明代码须要重构。高并发

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

Spring依赖解析流程

首先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是在相关依赖设置完成,而且相关的生命周期方法调用完毕后,才算是完成了初始化。

bean的延迟初始化

默认状况下ApplicationContext是提早初始化单例做用域的bean,做为ApplicationContext初始化的一部分。这样能够尽快的发现配置问题。能够经过指定bean的lazy-init="true",让bean在须要时才被初始化。

自动注入依赖

在Spring中能够自动注入依赖,能够减小指定属性或者构造器参数,还能够随着配置对象的变化来更新注入的对象。
自动注入依赖的模式有:经过名称注入,经过类型注入,和经过构造器注入

总结

本文总结了Spring中的依赖管理的基本原理和常见的问题,具体的依赖注入配置语法还须要参考Spring的官方文档来进行。


本文的重点是你有没有收获与成长,其他的都不重要,但愿读者们能谨记这一点。同时我通过多年的收藏目前也算收集到了一套完整的学习资料,包括但不限于:分布式架构、高可扩展、高性能、高并发、Jvm性能调优、Spring,MyBatis,Nginx源码分析,Redis,ActiveMQ、、Mycat、Netty、Kafka、Mysql、Zookeeper、Tomcat、Docker、Dubbo、Nginx等多个知识点高级进阶干货,但愿对想成为架构师的朋友有必定的参考和帮助

须要更详细架构师技能思惟导图和如下资料的能够加一下技术交流分享群:“708 701 457”免费获取