All the notes are from Spring Framework 5 Doc.

  一、Introduction to the Spring IOC Container and Beans

   org.springframework.beans 和  org.springframework.context两个包是Spring IOC容器的基础。

  BeanFactory接口提供了配置框架和基本功能,ApplicationContext接口则在此之上添加了更多满足企业应用规范的功能。

  在Spring中,构成应用程序主干并由SpringIoC容器管理的"对象"称为Bean。Spring负责Bean的实例化、装配和管理(整个生命周期)。

  所有Bean和它们之间的依赖关系,都反应在容器所使用的配置元数据(Configuration Metadata)中。

  二、Conainer Overview

  org.springframework.context.ApplicationContext代表了Spring IOC Container,因此它负责实例化、配置和装配Bean。

  容器通过读取配置元数据(Configuration Metadata)获取关于要实例化、配置和组装哪些对象的说明。而配置元数据可以是XML文件、注解以及Java代码。通过它们,可以很好地表示组成应用程序的对象以及这些对象之间的丰富相互依赖关系。

  如何通过这三种方式实例化ApplicationContext,在之前已经有提及过。

  官方文档提到,在大多数应用程序场景中,不需要显式地用代码实例化Spring IoC容器的一个或多个实例。例如在Web应用中,最简单的做法就是在web.xml中通过ContextLoaderListener注册一个ApplicationContext。

  三、Bean OverView

  

  四、Dependencies

  依赖注入(Dependency injection)是这样一个过程:

  对象只通过下面的三种方式定义他们的依赖关系(即与自己一起协作的其他对象)  

  • 构造函数的参数;
  • 工厂方法的参数;
  • 在对象的实例通过构造函数或者工厂方法返回后,注入其属性;

  然后,Spring Container在创建bean时便注入这些依赖。

  使用DI原则,代码更简洁,当对象具有依赖关系时,解耦更有效。

  对象不需要查找依赖项,也不知道依赖项的位置或类。因此,您的类变得更容易测试,特别是当它依赖于接口或抽象基类时。

  DI主要有两种形式:

  • 基于构造函数;
  • 基于Setter函数——基于setter的DI是在调用无参构造函数或无参静态工厂方法来实例化bean之后,在bean上调用setter方法来完成的。

  对于这两种方式,有个最佳实践:

  对强制依赖项使用构造函数,为可选依赖项使用setter方法或配置方法( configuration methods)。注意,在setter方法上使用@Required注释可以使属性成为必需的依赖项。

  Spring Team通常提倡构造函数注入,因为它允许您将应用程序组件实现为不可变对象,并确保所需的依赖项不是空的。此外,通过构造函数注入的组件总是以完全初始化后的状态返回给客户端的(调用)代码。

  顺便提一句,构造函数参数过多是一种糟糕的代码,这意味着类可能承担了太多的责任。对此应该进行重构,以更好分离所关注的点。

  而Setter注入应该主要用于可选的依赖项,这些依赖项可以在类中分配合理的默认值。不然的话,在任何使用该依赖项的地方都需要进行非空检查。Setter注入的一个优势是setter方法使该类的对象能够在以后重新进行配置或重新注入。

  特殊情况下,例如,如果第三方类不公开任何setter方法,则构造函数注入可能是惟一可用的DI形式。

  IOC Container是完成DI的步骤:

  • 首先,使用描述所有bean的配置元数据来创建和初始化ApplicationContext。配置元数据可以由XML、Java代码或注释指定。
  • 然后,对于每个bean,其依赖项以属性、构造函数参数或静态工厂方法的参数的形式表示(如果您使用它而不是普通的构造函数)。当bean实际被创建时,这些依赖项将提供给bean。
  • 接着,每个属性或构造函数参数都是要设置的值的实际定义,或者是对容器中另一个bean的引用。
  • 最后,每个作为值的属性或构造函数参数都从其指定的格式转换为该属性或构造函数参数的实际类型。默认情况下,Spring可以将以字符串格式提供的值转换为所有内置类型,例如int、long、string、boolean等等。

  事实上,Spring的Container在被创建时就会验证每个bean的配置,尽管bean的属性直到bean在被创建时才被设置。

  但是singleton-scoped和pre-instantiated (默认情况)的bean都是在Container创建时被创建。否在,bean都是在被请求时才被创建。

  一个bean的创建可能会引起一系列的bean被创建,因为它的依赖项,以及依赖项的依赖项都会被创建和分配。

  

  引申:关于循环依赖

  如果主要使用构造函数注入,则可能会产生一个无法解决的“循环依赖”的场景。

  例如:Class A requires an instance of class B through constructor injection, and class B requires an instance of class A through constructor injection. If you configure beans for classes A and B to be injected into each other, the Spring IoC container detects this circular reference at runtime, and throws a BeanCurrentlyInCreationException.

  一种解决方案是:让其中的一些类使用setter方法进行依赖注入。或者,全都只使用setter方法。换句话说,尽管不建议这样做,但可以使用setter注入解决循环依赖的问题。

  在创建bean时,Spring会尽可能晚地去设置其属性以及解决其依赖项。这意味着,在你请求一个对象时,如果在创建对象或解决其依赖项时出现问题,正确加载的Spring容器可能稍晚才会生成异常。这也是为什么ApplicationContext的实现类默认会预先初始化单例的bean。在这些bean被实际请求前,花费一些前期时间和内存来创建他们,可以保证在ApplicationContext创建时发现一些配置问题。

  当然你也可以覆盖这种默认的行为,让singleton bean晚点被初始化。

  在不存在依赖循坏的情况下,如果Bean A依赖于Bean B,那么Spring会在完全初始化Bean B后,再进行将其注入A中。

  五、Bean Scopes

  Spring框架支持六个bean的作用域,而在web相关的ApplicaitonContext中,只支持其中四个。

  还可以创建自定义scope。

  以下是六种作用域,后四个是web相关:

  singleton---一个bean的定义,在一个IOC容器中只会有它的一个实例。这意味着每次对这个容器中这个bean的请求,返回的都是同一个实例。

  prototype---一个bean的定义,在一个IOC容器中可以有多个实例。每次的请求,都会引起同一个bean的新的实例的创建。

  request--- bean作用于HTTP request的生命周期,而每个HTTP request都拥有它自己的实例bean,这个bean的声明周期也随同request的生命周期。只在web相关的Spring ApplicationContext中才有意义。

  session--- bean作用于HTTP session的生命周期,每个HTTP session都有自己的实例bean。

  application--- Scopes a single bean definition to the lifecycle of a ServletContext.

  websocket---Scopes a single bean definition to the lifecycle of a WebSocket。

  

  对于singleton和prototype的使用,有一个原则:应该对所有“有状态”的bean使用prototype作用域,对“无状态”的bean使用单例作用域。

  数据访问对象(DAO)通常不配置为原型,因为典型的DAO不包含任何会话状态。

  与其他作用域不同,Spring并不管理prototype bean的完整生命周期。

  容器在初始化并配置好一个prototype对象后,就把它交给客户端,此后不在有这个prototype对象实例的任何记录。因此,尽管对所有对象都调用初始化生命周期回调方法,而不管作用域如何,但在prototype 的情况下,配置的销毁生命周期回调方法不会被调用。而客户端代码必须自己清理prototype实例对象并且释放它所占用的资源。Spring也为此提供了一个专用的容器,来释放被这些prototype-scoped bean所占用的资源(try using a custom bean post-processor, which holds a reference to beans that need to be cleaned up)。

  某种程度上来说,Spring容器在prototype bean中的角色只是是Java new操作符的替代品。此后的所有生命周期管理都必须由客户端来处理。

  

  

  

  

  

  

Spring IOC Container的更多相关文章

  1. Spring IoC Container and Spring Bean Example Tutorial

    Spring Framework is built on the Inversion of Control (IOC) principle. Dependency injection is the t ...

  2. Spring IoC Container源码分析(二)-bean初始化流程

    准备 Person实例 @Data public class Person { private String name; private int age; } xml bean配置 <?xml ...

  3. Spring IOC Container原理解析

    Spring Framework 之 IOC IOC.DI基础概念 关于IOC和DI大家都不陌生,我们直接上martin fowler的原文,里面已经有DI的例子和spring的使用示例 <In ...

  4. Spring-Framework-官方文档阅读(一)Spring IoC Container

    通读Spring IoC容器官方文档,对IoC容器有一个大致的了解. 环境 JDK1.8 Spring Framework Version :4.3.18.RELEASE 容器概述 接口org.spr ...

  5. Spring学习笔记之三----基于Annotation的Spring IOC配置

    使用Annotation 来创建Bean有两种方式 在配置类中创建bean(配置类是指标注为@Configuration的类),在配置类中每一个创建bean的方法都应该标注为@Bean,可以在@Bea ...

  6. 【Spring】初始化Spring IoC容器(非Web应用),并获取Bean

    参考文章 Introduction to the Spring IoC container and beans BeanFactory 和ApplicationContext(Bean工厂和应用上下文 ...

  7. Spring IOC小记

    1. What IOC (Inversion Of Control,控制反转)与DI(Dependency Injecion,依赖注入) 用于对象间解耦,如在以前若对象A依赖B则需要在A中负责B的创建 ...

  8. 一分钟玩转 Spring IoC

    前言 「上一篇文章」我们对 Spring 有了初步的认识,而 Spring 全家桶中几乎所有组件都是依赖于 IoC 的. 刚开始听到 IoC,会觉得特别高大上,但其实掰开了很简单. 跟着我的脚步,一文 ...

  9. 一分钟玩转 Spring IoC!

    前言 「上一篇文章」我们对 Spring 有了初步的认识,而 Spring 全家桶中几乎所有组件都是依赖于 IoC 的. 刚开始听到 IoC,会觉得特别高大上,但其实掰开了很简单. 跟着我的脚步,一文 ...

随机推荐

  1. Js 之复制到剪贴板 clipboard.js

    一.下载 https://github.com/zenorocha/clipboard.js/archive/master.zip 二.Demo示例 <!DOCTYPE html> < ...

  2. 运维自动化之ansible

    Ansible简介 Ansible是一个简单的自动化运维管理工具,基于Python语言实现,由Paramiko和PyYAML两个关键模块构建,可用于自动化部署应用.配置.编排task(持续交付.无宕机 ...

  3. Python实现按照指定要求逆序输出一个数字的方法

    Python实现按照指定要求逆序输出一个数字的方法 这篇文章主要介绍了Python实现按照指定要求逆序输出一个数字的方法,涉及Python针对字符串的遍历.判断.输出等相关操作技巧,需要的朋友可以参考 ...

  4. Response 与 Cookie

    Response 与 Cookie Web服务器要完成的任务的最后一步就是向客户端返回数据.如果客户端是浏览器,那么返回的数据通常是HTML.JS.CSS或者其他类型的代码. Cookie是保存在客户 ...

  5. 神经网络(NN)实现多分类-----Keras实现

    IRIS数据集介绍   IRIS数据集(鸢尾花数据集),是一个经典的机器学习数据集,适合作为多分类问题的测试数据,它的下载地址为:http://archive.ics.uci.edu/ml/machi ...

  6. OPC 数据交互环境配置

    本文源自ioufev先生的博客<OPC和DCOM配置>(https://www.cnblogs.com/ioufev/p/9365919.html)及「geekc」先生的<OPC工作 ...

  7. Public thanks to Shao Qirui for his contribution to open source software

    Public thanks to Shao Qirui for his contribution to open source softwareShao Qirui is a student, but ...

  8. 源码搭建zabbix服务

    1) 部署LNMP 1.1) cd /root tar -xf lnmp_soft.tar.gz cd lnmp_soft/ tar -xf nginx-1.10.3.tar.gz cd nginx- ...

  9. mysql导入问题

      今天在导入数据库的时候,发现此问题: 后来一查,是因为GTID_EXECUTED有值,而导出的文件中包含了SET @@GLOBAL.GTID_PURGED的操作,所以导入报错. 我们有两种方法解决 ...

  10. HTTP请求方法:GET、HEAD、POST、PUT、DELETE、CONNECT、OPTIONS、TRACE 说明

    平时的Rest开发,用到的都是GET,POST,PUT,DELETE类型的请求. 但Rest支持的请求类型不止前面4种,还有其他几种. 下面部分转自: https://www.html.cn/arch ...