热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【spring】(二)spring的IOC理解

目录一、IOC是什么二、IoC能做什么三、IoC和DI四、SpringIoC容器4.1SpringIoC容器的设计4.1.1BeanFactory4.1.2ApplicationC

目录



  • 一、IOC是什么

  • 二、IoC能做什么

  • 三、IoC和DI

  • 四、Spring IoC容器

    • 4.1 Spring IoC 容器的设计

      • 4.1.1 BeanFactory

      • 4.1.2 ApplicationContext

      • 4.1.3 ApplicationContext 常见实现类:

      • 4.1.4 BeanFactory 和 ApplicationContext 的区别


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

    • 4.3 IoC 是如何实现的


@

本文参考

https://www.cnblogs.com/xdp-gacl/p/4249939.html

https://www.cnblogs.com/wmyskxz/p/8824597.html


一、IOC是什么

IoC ——Inversion of control,即控制反转,不是什么技术,而是一种思想。在Java 开发中,意味着将你设计好的

对象交给容器控制,而不是传统的自己直接控制。理解IOC,关键在于理解谁控制谁,控制什么,为何事反转,哪些地方反转了。那我们来分析一下。



  • 谁控制谁,控制什么:传统的Java SE程序设计中,我们直接在对象内部通过new进行创建对象,是程序主动的去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由IoC容器来控制对象的创建;谁控制谁?当然是IoC容器控制了对象;控制什么?那就是主要控制了外部资源获取(不只是对象包括文件等等


  • 为何是反转?哪些地方反转了: 有反转就由正转,传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象;为何事反转?因为由容器帮我们查找及注入依赖对象,对象只是被动地接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。


传统程序设计如图,都是主动创建相关对象后再组合起来。

在这里插入图片描述

有了IoC/DI容器后,在客户端类中不再主动去创建这些对象了,如图

在这里插入图片描述


二、IoC能做什么

IoC 不是一种技术,只是一种思想,一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合、更优良的程序。传统应用程序都是由我们在类内部主动创建依赖对象,从而导致类与类之间高耦合,难于测试;有了IoC容器后,把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以对象与对象之间是 松散耦合,这样也方便测试,利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活。

其实IoC对编程带来的最大改变不是从代码上,而是从思想上,发生了“主从换位”的变化。应用程序原本是老大,要获取什么资源都是主动出击,但是在IoC/DI思想中,应用程序就变成被动的了,被动的等待IoC容器来创建并注入它所需要的资源了。

IoC很好的体现了面向对象设计法则之一—— 好莱坞法则:“别找我们,我们找你”;即由IoC容器帮对象找相应的依赖对象并注入,而不是由对象主动去找。


三、IoC和DI

DI-Dependency Injection,即依赖注入:组件之间的依赖关系由容器在运行期间决定,形象地说,即由容器动态地将某个依赖关系注入到组件之中,依赖注入的目的并非为软件紫铜带来更多的功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。

理解DI的关键是:谁依赖谁,为什么需要依赖,谁注入谁。注入了什么?



  • 谁依赖谁:应用程序依赖于IoC容器

  • 为什么需要依赖:应用程序需要IoC容器来提供对象需要的外部资源

  • 谁注入谁:很明显是IoC容器注入应用程序某个对象,应用程序依赖的对象

  • 注入了什么:就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)

IoC和DI由什么关系呢?其实它们是同一个概念的不同角度描述,由于控制反转概念比较含糊(可能只是理解为容器控制对象这一个层面,很难让人想到谁来维护对象关系),所以2004年大师级人物Martin Fowler又给出了一个新的名字:“依赖注入”,相对IoC 而言,“依赖注入”明确描述了“被注入对象依赖IoC容器配置依赖对象”


四、Spring IoC容器

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


4.1 Spring IoC 容器的设计

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



  • BeanFactory

  • ApplicationContext

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

在这里插入图片描述


4.1.1 BeanFactory

从上图中我们可以看到,BeanFactory位于设计的最底层,它提供了Spring IoC最底层。为此,我们先看看该类中提供了哪些方法。在这里插入图片描述

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



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

    1. 按照类型拿bean:

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

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

    2. 按照bean的名字拿bean:

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

      这种方式不太安全,IDE不会检查其安全性(关联性)

    3. 按照名字和类型拿bean(推荐)

      java bean = (Bean) factory.getBean("beanName", bean.class);


  • 【isSingleton】用于判断是否单例,如果判断为真,其意思是该Bean在容器中是作为一个唯一单例存在的。

    【isPrototype】则相反,如果判断为真,意思是当你从容器中获取Bean,容器就为你生成一个新的实例。

    注意;在默认情况下,isSingleton为true,而isPrototype为false

  • 关于type的匹配,这是一个按 Java 类型匹配的方式

  • 【getAliases】方法是获取别名的方法

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


4.1.2 ApplicationContext

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

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

1、先在【src】目录下创建一个 【bean.xml】 文件:


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">






这里就定义了一个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 的装配以及一些细节,会在下一篇文章中讲到


4.1.3 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(); // 初始化容器

4.1.4 BeanFactory 和 ApplicationContext 的区别



  • BeanFactory

    是Spring中最底层的接口,只提供最简单的IoC功能,负责配置、创建和故哪里bean。在应用中,一般不使用BeanFactory,而推荐使用ApplicationContext(应用上下文),原因如下:

  • ApplicationContext

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

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

    (1)支持国际化

    (2)支持消息机制

    (3)支持统一的资源加载

    (4)支持AOP功能


4.2 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 的初始化,完成依赖注入。


4.3 IoC 是如何实现的

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



  1. 读取标注或者配置文件,看看JuiceMaker依赖的是哪个Source,拿到类名

  2. 使用反射的API,基于类名实例化对应的对象实例

  3. 将对象实例,通过构造函数或者 setter,传递给 JuiceMaker

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


推荐阅读
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • Tomcat/Jetty为何选择扩展线程池而不是使用JDK原生线程池?
    本文探讨了Tomcat和Jetty选择扩展线程池而不是使用JDK原生线程池的原因。通过比较IO密集型任务和CPU密集型任务的特点,解释了为何Tomcat和Jetty需要扩展线程池来提高并发度和任务处理速度。同时,介绍了JDK原生线程池的工作流程。 ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
  • SpringBoot整合SpringSecurity+JWT实现单点登录
    SpringBoot整合SpringSecurity+JWT实现单点登录,Go语言社区,Golang程序员人脉社 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • 在重复造轮子的情况下用ProxyServlet反向代理来减少工作量
    像不少公司内部不同团队都会自己研发自己工具产品,当各个产品逐渐成熟,到达了一定的发展瓶颈,同时每个产品都有着自己的入口,用户 ... [详细]
  • 标题: ... [详细]
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • 单点登录原理及实现方案详解
    本文详细介绍了单点登录的原理及实现方案,其中包括共享Session的方式,以及基于Redis的Session共享方案。同时,还分享了作者在应用环境中所遇到的问题和经验,希望对读者有所帮助。 ... [详细]
  • IjustinheritedsomewebpageswhichusesMooTools.IneverusedMooTools.NowIneedtoaddsomef ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • Activiti7流程定义开发笔记
    本文介绍了Activiti7流程定义的开发笔记,包括流程定义的概念、使用activiti-explorer和activiti-eclipse-designer进行建模的方式,以及生成流程图的方法。还介绍了流程定义部署的概念和步骤,包括将bpmn和png文件添加部署到activiti数据库中的方法,以及使用ZIP包进行部署的方式。同时还提到了activiti.cfg.xml文件的作用。 ... [详细]
author-avatar
蒋诽盐
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有