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. 学PHP应注意的问题与知识点

    编出一手好代码,这个是需要你在平时开发中日积月累的,平时如果你有注意到以下的那些代码的编码,那么祝贺你,你在技能提升这方面已经垫下了一些基础,编写出一手好代码,说白了就是你特么注意到性能这块的问题,代 ...

  2. 分布式系统的应用程序性能监视工具,专为微服务、云本机架构和基于容器(Docker、K8s、Mesos)架构而设计。 SkyWalking

    Apache SkyWalking™ | SkyWalking Teamhttp://skywalking.apache.org/zh/ Application performance monitor ...

  3. SQL-W3School-高级:SQL CREATE INDEX 语句

    ylbtech-SQL-W3School-高级:SQL CREATE INDEX 语句 1.返回顶部 1. CREATE INDEX 语句用于在表中创建索引. 在不读取整个表的情况下,索引使数据库应用 ...

  4. ubuntu 安装的一些软件

    https://github.com/wszqkzqk/deepin-wine-ubuntu 14 版本的ubuntu  安装发生问题; 16 18 的都可以安装成功微信;

  5. stm32第一章cortex-M3处理器概述

    处理器特点 哈弗结构3级流水线内核 实现Thumb-2指令集,告别切换32位的arm指令和16位的Thumb指令,优化性能和代码密度 结合可配置的嵌套向量中段控制器Nvic,提供非屏蔽中断NMI和32 ...

  6. Docker使用Portainer搭建可视化界面

    Portainer介绍 Portainer是Docker的图形化管理工具,提供状态显示面板.应用模板快速部署.容器镜像网络数据卷的基本操作(包括上传下载镜像,创建容器等操作).事件日志显示.容器控制台 ...

  7. ORB-特征点提取代码比较

    ORB特征提取代码测试 整合ICE-BA.ORB-SLAM2.openvslam中的ORB提取代码,并比较速度,方便以后使用 1. ORB-SLAM2 vsICE-BA vs openvslam IC ...

  8. 【AMAD】django-channels -- 为Django带来异步开发

    动机 简介 个人评分 动机 目前web生态的发展带来了很多异步特性,比如websocket.而原生Django并不支持. 简介 django-channels1为Django带来了Websocket, ...

  9. winform 更新文件上传(一)

    using Common; using DevExpress.XtraEditors; using FileModel.UpLoad; using System; using System.Colle ...

  10. 【计算机视觉】深度相机(八)--OpenNI及与Kinect for windows SDK的比较

    OpenNI(开放自然交互)是一个多语言,跨平台的框架,它定义了编写应用程序,并利用其自然交互的API.OpenNI API由一组可用来编写通用自然交互应用的接口组成.OpenNI的主要目的是要形成一 ...