Spring IoC 概述

IoC:Inverse of Control(控制反转)

  • 读作“反转控制”,更好理解,不是什么技术,而是一种设计思想,就是将原本在程序中手动创建对象的控制权,交由Spring框架来管理。
  • 正控:若要使用某个对象,需要自己去负责对象的创建
  • 反控:若要使用某个对象,只需要从 Spring 容器中获取需要使用的对象,不关心对象的创建过程,也就是把创建对象的控制权反转给了Spring框架
  • 好莱坞法则:Don’t call me ,I’ll call you

一个例子

控制反转显然是一个抽象的概念,我们举一个鲜明的例子来说明。

在现实生活中,人们要用到一样东西的时候,第一反应就是去找到这件东西,比如想喝新鲜橙汁,在没有饮品店的日子里,最直观的做法就是:买果汁机、买橙子,然后准备开水。值得注意的是:这些都是你自己“主动”创造的过程,也就是说一杯橙汁需要你自己创造。

然而到了今时今日,由于饮品店的盛行,当我们想喝橙汁时,第一想法就转换成了找到饮品店的联系方式,通过电话等渠道描述你的需要、地址、联系方式等,下订单等待,过一会儿就会有人送来橙汁了。

请注意你并没有“主动”去创造橙汁,橙汁是由饮品店创造的,而不是你,然而也完全达到了你的要求,甚至比你创造的要好上那么一些。

Spring IoC 阐述

这就是一种控制反转的理念,上述的例子已经很好的说明了问题,我们再来描述一下控制反转的概念:控制反转是一种通过描述(在 Java 中可以是 XML 或者注解)并通过第三方(Spring)去产生或获取特定对象的方式。

  • 好处:

    降低对象之间的耦合

    我们不需要理解一个类的具体实现,只需要知道它有什么用就好了(直接向 IoC 容器拿)

主动创建的模式中,责任归于开发者,而在被动的模式下,责任归于 IoC 容器,基于这样的被动形式,我们就说对象被控制反转了。(也可以说是反转了控制)


Spring IoC 容器

Spring 会提供 IoC 容器来管理和容纳我们所开发的各种各样的 Bean,并且我们可以从中获取各种发布在 Spring IoC 容器里的 Bean,并且通过描述可以得到它。

Spring IoC 容器的设计

Spring IoC 容器的设计主要是基于以下两个接口:

  • BeanFactory
  • ApplicationContext

其中 ApplicationContext 是 BeanFactory 的子接口之一,换句话说:BeanFactory 是 Spring IoC 容器所定义的最底层接口,而 ApplicationContext 是其最高级接口之一,并对 BeanFactory 功能做了许多的扩展,所以在绝大部分的工作场景下,都会使用 ApplicationContext 作为 Spring IoC 容器。

BeanFactory

从上图中我们可以几乎看到, BeanFactory 位于设计的最底层,它提供了 Spring IoC 最底层的设计,为此,我们先来看看该类中提供了哪些方法:

由于这个接口的重要性,所以有必要在这里作一下简短的说明:

  • 【getBean】 对应了多个方法来获取配置给 Spring IoC 容器的 Bean。

    ① 按照类型拿 bean:

    bean = (Bean) factory.getBean(Bean.class);

    注意:要求在 Spring 中只配置了一个这种类型的实例,否则报错。(如果有多个那 Spring 就懵了,不知道该获取哪一个)

    ② 按照 bean 的名字拿 bean:

    bean = (Bean) factory.getBean("beanName");

    注意:这种方法不太安全,IDE 不会检查其安全性(关联性)

    ③ 按照名字和类型拿 bean:(推荐)

    bean = (Bean) factory.getBean("beanName", Bean.class);
  • 【isSingleton】 用于判断是否单例,如果判断为真,其意思是该 Bean 在容器中是作为一个唯一单例存在的。而【isPrototype】则相反,如果判断为真,意思是当你从容器中获取 Bean,容器就为你生成一个新的实例。

    注意:在默认情况下,【isSingleton】为 ture,而【isPrototype】为 false
  • 关于 type 的匹配,这是一个按 Java 类型匹配的方式
  • 【getAliases】方法是获取别名的方法

这就是 Spring IoC 最底层的设计,所有关于 Spring IoC 的容器将会遵守它所定义的方法。

ApplicationContext

根据 ApplicationContext 的类继承关系图,可以看到 ApplicationContext 接口扩展了许许多多的接口,因此它的功能十分强大,所以在实际应用中常常会使用到的是 ApplicationContext 接口,因为 BeanFactory 的方法和功能较少,而 ApplicationContext 的方法和功能较多。

通过上一篇 IoC 的例子,我们来认识一个 ApplicationContext 的子类——ClassPathXmlApplicationContext。

  1. 先在【src】目录下创建一个 【bean.xml】 文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 通过 xml 方式装配 bean -->
<bean name="source" class="pojo.Source">
<property name="fruit" value="橙子"/>
<property name="sugar" value="多糖"/>
<property name="size" value="超大杯"/>
</bean>
</beans>
  1. 这里定义了一个 bean ,这样 Spring IoC 容器在初始化的时候就能找到它们,然后使用 ClassPathXmlApplicationContext 容器就可以将其初始化:
ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
Source source = (Source) context.getBean("source", Source.class); System.out.println(source.getFruit());
System.out.println(source.getSugar());
System.out.println(source.getSize());

这样就会使用 Application 的实现类 ClassPathXmlApplicationContext 去初始化 Spring IoC 容器,然后开发者就可以通过 IoC 容器来获取资源了啦!

关于 Spring Bean 的装配以及一些细节,会在下一篇文章中讲到

ApplicationContext 常见实现类:

1.ClassPathXmlApplicationContext:

读取classpath中的资源

ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

2:FileSystemXmlApplicationContext:-

读取指定路径的资源

ApplicationContext ac = new FileSystemXmlApplicationContext("c:/applicationContext.xml");

3.XmlWebApplicationContext:

需要在Web的环境下才可以运行

XmlWebApplicationContext ac = new XmlWebApplicationContext(); // 这时并没有初始化容器
ac.setServletContext(servletContext); // 需要指定ServletContext对象
ac.setConfigLocation("/WEB-INF/applicationContext.xml"); // 指定配置文件路径,开头的斜线表示Web应用的根目录
ac.refresh(); // 初始化容器

BeanFactory 和 ApplicationContext 的区别:

  • BeanFactory:是Spring中最底层的接口,只提供了最简单的IoC功能,负责配置,创建和管理bean。

    在应用中,一般不使用 BeanFactory,而推荐使用ApplicationContext(应用上下文),原因如下。
  • ApplicationContext:

    1.继承了 BeanFactory,拥有了基本的 IoC 功能;

    2.除此之外,ApplicationContext 还提供了以下功能:

    ① 支持国际化;

    ② 支持消息机制;

    ③ 支持统一的资源加载;

    ④ 支持AOP功能;

Spring IoC 的容器的初始化和依赖注入

虽然 Spring IoC 容器的生成十分的复杂,但是大体了解一下 Spring IoC 初始化的过程还是必要的。这对于理解 Spring 的一系列行为是很有帮助的。

注意:Bean 的定义和初始化在 Spring IoC 容器是两大步骤,它是先定义,然后初始化和依赖注入的。

  • Bean 的定义分为 3 步:

    1.Resource 定位

    Spring IoC 容器先根据开发者的配置,进行资源的定位,在 Spring 的开发中,通过 XML 或者注解都是十分常见的方式,定位的内容是由开发者提供的。

    2.BeanDefinition 的载入

    这个时候只是将 Resource 定位到的信息,保存到 Bean 定义(BeanDefinition)中,此时并不会创建 Bean 的实例

    3.BeanDefinition 的注册

    这个过程就是将 BeanDefinition 的信息发布到 Spring IoC 容器中

    注意:此时仍然没有对应的 Bean 的实例。

做完了以上 3 步,Bean 就在 Spring IoC 容器中被定义了,而没有被初始化,更没有完成依赖注入,也就是没有注入其配置的资源给 Bean,那么它还不能完全使用。

对于初始化和依赖注入,Spring Bean 还有一个配置选项——【lazy-init】,其含义就是是否初始化 Spring Bean。在没有任何配置的情况下,它的默认值为 default,实际值为 false,也就是 Spring IoC 默认会自动初始化 Bean。如果将其设置为 true,那么只有当我们使用 Spring IoC 容器的 getBean 方法获取它时,它才会进行 Bean 的初始化,完成依赖注入。


IoC 是如何实现的

最后我们简单说说IoC是如何实现的。想象一下如果我们自己来实现这个依赖注入的功能,我们怎么来做? 无外乎:

  1. 读取标注或者配置文件,看看JuiceMaker依赖的是哪个Source,拿到类名
  2. 使用反射的API,基于类名实例化对应的对象实例
  3. 将对象实例,通过构造函数或者 setter,传递给 JuiceMaker

我们发现其实自己来实现也不是很难,Spring实际也就是这么做的。这么看的话其实IoC就是一个工厂模式的升级版!当然要做一个成熟的IoC框架,还是非常多细致的工作要做,Spring不仅提供了一个已经成为业界标准的Java IoC框架,还提供了更多强大的功能,所以大家就别去造轮子啦!希望了解IoC更多实现细节不妨通过学习Spring的源码来加深理解!

引用地址:这里

【参考资料】:《Java EE 互联网轻量级框架整合开发》、《Spring 实战(第四版)》

【好文推荐】:①Spring 的本质系列(1) -- 依赖注入②Spring的IoC原理


欢迎转载,转载请注明出处!

简书ID:@我没有三颗心脏

github:wmyskxz

欢迎关注公众微信号:wmyskxz_javaweb

分享自己的Java Web学习之路以及各种Java学习资料

Spring(2)——Spring IoC 详解的更多相关文章

  1. Spring IoC详解

    Spring IoC详解 1. 控制反转 控制反转是一种通过描述(XML或者注解)并通过第三方去产生或获取特定对象的方式.在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Depend ...

  2. spring框架 AOP核心详解

    AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等待,Struts2的拦截器设计就是基于AOP的思想,是个比较经典的例子. 一 AOP的基本概念 (1)Asp ...

  3. Spring各个jar包详解

    Spring各jar包详解 spring.jar 是包含有完整发布模块的单个jar 包.但是不包括mock.jar,aspects.jar, spring-portlet.jar, and sprin ...

  4. Spring框架系列(9) - Spring AOP实现原理详解之AOP切面的实现

    前文,我们分析了Spring IOC的初始化过程和Bean的生命周期等,而Spring AOP也是基于IOC的Bean加载来实现的.本文主要介绍Spring AOP原理解析的切面实现过程(将切面类的所 ...

  5. Spring框架系列(10) - Spring AOP实现原理详解之AOP代理的创建

    上文我们介绍了Spring AOP原理解析的切面实现过程(将切面类的所有切面方法根据使用的注解生成对应Advice,并将Advice连同切入点匹配器和切面类等信息一并封装到Advisor).本文在此基 ...

  6. Spring框架系列(11) - Spring AOP实现原理详解之Cglib代理实现

    我们在前文中已经介绍了SpringAOP的切面实现和创建动态代理的过程,那么动态代理是如何工作的呢?本文主要介绍Cglib动态代理的案例和SpringAOP实现的原理.@pdai Spring框架系列 ...

  7. Spring框架系列(12) - Spring AOP实现原理详解之JDK代理实现

    上文我们学习了SpringAOP Cglib动态代理的实现,本文主要是SpringAOP JDK动态代理的案例和实现部分.@pdai Spring框架系列(12) - Spring AOP实现原理详解 ...

  8. Spring Data操作Redis详解

    Spring Data操作Redis详解 Redis是一种NOSQL数据库,Key-Value形式对数据进行存储,其中数据可以以内存形式存在,也可以持久化到文件系统.Spring data对Redis ...

  9. elasticSearch+spring 整合 maven依赖详解

    摘自:http://www.mayou18.com/detail/nTxPQSyu.html [Elasticsearch基础]elasticSearch+spring 整合 maven依赖详解 Ma ...

  10. Spring Aop底层原理详解

    Spring Aop底层原理详解(来源于csdn:https://blog.csdn.net/baomw)

随机推荐

  1. [机器学习Lesson 1 Introduction] 机器学习的动机与应用

    1. Machine Learning definition(机器学习定义) Arthur Samuel(1959年)将机器学习非正式定义为:在不直接针对问题进行编程的情况下,赋予计算机学习能力的一个 ...

  2. npm scripts 使用指南

    转载自:http://www.ruanyifeng.com/blog/2016/10/npm_scripts.html Node 开发离不开 npm,而脚本功能是 npm 最强大.最常用的功能之一. ...

  3. Android_scaleType属性

    这里我们重点理解ImageView的属性android:scaleType,即ImageView.setScaleType(ImageView.ScaleType).android:scaleType ...

  4. Python中的classmethod与staticmethod

    首先,这是一个经典的问题. 我们首先做一个比较: classmethod的第一个参数是cls,即调用的时候要把类传入 这意味着我们我们可以在classmethod里使用类的属性,而不是类的实例的属性( ...

  5. 第1次作业:小菜鸟的平凡IT梦

    #1.结缘计算机的始末 ##1.1与计算机相识的几年 作为一个95后,出生在一个互联网开始兴盛的时代.我记得小学的时候,开始知道电脑这个东西,学校有了机房,开始有了所谓的电脑课.那时候计算机对于我来说 ...

  6. C语言--函数嵌套

    一.实验作业 注意: 1.可以先初始化2个结构体数组数据以便测试. 2.要求用模块化方式组织程序结构,合理设计各自定义函数.同时,程序能够进行异常处理,检查用户输入数据的有效性,用户输入数据有错误,如 ...

  7. C语言博客作业—函数

    一.PTA实验作业 题目1:使用函数输出水仙花数 1. 本题PTA提交列表 2. 设计思路 (1)首先定义函数narcissistic(number)判断number是否为水仙花数: (2)narc用 ...

  8. 每日冲刺报告——Day3(Java-Team)

    第三天报告(11.4  周六) 团队:Java-Team 成员: 章辉宇(284) 吴政楠(286) 陈阳(PM:288) 韩华颂(142) 胡志权(143) github地址:https://git ...

  9. 项目Alpha冲刺Day9

    一.会议照片 二.项目进展 1.今日安排 侧栏及相关刷新完成,项目结构小变动.个人信息和修改密码后台完成. 2.问题困难 前后台联调出现问题,配置修改了半天还没改好.好像是会话丢失,初步判断应该是后台 ...

  10. 关于FPGA随笔

    verilog与c