水晶帘动微风起,满架蔷薇一院香。

概述

在软件工程中,控制反转(IoC)是一种设计思想,对象之间耦合在一起,在运行时自动绑定,并且它们编译时对所需要引用的对象是不确定的。在这个spring教程中,通过示例了解iocspring中的依赖注入之间的区别。

什么是控制反转(IOC)

在传统面向对象设计的软件系统中,它的底层由N多个对象构成,各个对象之间通过相互合作。最终实现业务流程。控制反转意指把创建和查找依赖对象的控制权交给了容器,由容器进行注入组合对象,所以对象与对象之间是松散耦合,这样也方便测试,利于功能复用,更重要的是使得程序的整个体系结构变得非常灵活,尽管有些人认为使用服务定位器模式也可以提供控制反转。

使用控制反转作为设计准则有以下优点:

  1. 某个任务的执行与实现是分离的
  2. 每个模块更关注与自己的设计。
  3. 模块不需要关注其它系统,只需要依赖即可。
  4. 模块的升级不会影响其它模块

什么是依赖注入(DI)

IoC是一种设计范例,其目标是对应用程序的各个组件提供更多控制,使这些组件可以完成工作。依赖注入是一种模式,用于创建对象依赖的对象实例,且在编译时期是无感知的。IoC依赖于依赖注入,因为它需要一种机制来创建且引用需要的组件。

这两个概念以这种方式协同工作,允许编写更灵活、可重用和封装的代码。因此,它们是设计面向对象解决方案的重要概念。

如何实现IoC

在面向对象的编程中,有几种基本技术可以实现控制反转。如下:

  1. 使用工厂模式
  2. 使用服务定位器模式
  3. 使用以下任何给定类型的依赖项注入
  • 构造函数注入
  • setter注入
  • 注解注入

Spring中的控制反转

org.springframework.beansorg.springframework.context包为Spring框架的IoC容器提供了基础功能。BeanFactory接口提供了更高级的配置项,能够管理所有对象。ApplicationContext接口建立在BeanFactory之上(它是一个子接口),并添加了其他功能,例如与SpringAOP功能的更轻松集成,消息资源处理(用于国际化),事件传播以及特定于应用程序层的上下文,例如作为Web应用程序中使用的WebApplicationContext

BeanFactorySpring IoC容器的主要实现,负责包含和管理上述BeanBeanFactory接口是Spring中的重要的IoC容器接口。

BeanFactory接口有许多实现。最常用的BeanFactory实现是XmlBeanFactory类。其他常用的类是XmlWebApplicationContext。根据bean的定义,工厂将返回所包含对象的不同实例(Prototype设计模式),或者返回单个共享实例(Singleton设计模式,其中实例是作用域中的单例)。的工厂)。将返回哪种类型的实例取决于bean工厂的配置:获取bean实例的API是相同的。

在深入研究依赖注入类型之前,首先确定在spring框架中创建bean的方式,因为它将有助于理解下一部分的内容。

如何在Spring中创建bean实例

Bean定义可以看作是创建一个或多个实际对象的配置。获取时,容器会查看命名bean的配置,并使用该bean定义封装的配置项来创建(或获取)实际对象。

使用构造函数

当使用构造函数方法创建bean时,所有普通类都可以被Spring使用并与之兼容。也就是说,正在创建的类不需要实现任何特定的接口或以特定的方式进行编码。仅指定bean类就足够了。使用基于XML的配置项时,可以像这样指定bean类:

<bean id="exampleBean" class = "cn.howtodoinjava.ExampleBean"/>

使用静态工厂方法

在定义要使用静态工厂方法创建的bean以及指定包含静态工厂方法的类的class属性时,需要另一个名为factory-method的属性来指定工厂方法本身的名称。

<bean id="exampleBean" class = "cn.howtodoinjava.ExampleBean" factory-method="createInstance"/>

Spring希望能够调用此方法并返回一个可用的对象,得到对象之后,该对象将被视为是通过构造函数创建的。

使用实例工厂方法

以类似于通过静态工厂方法进行实例化的方式,使用实例工厂方法进行实例化是调用容器中现有beanfactory方法来创建新bean

<bean id="myFactoryBean"  class="cn.howtodoinjava.MyFactoryBean">

<bean id="exampleBean"  factory-bean="myFactoryBean" factory-method="createInstance"></bean>

Spring的依赖注入

依赖项注入(DI)背后的基本原则是,对象仅通过构造函数参数、工厂方法的参数或属性来定义它们的依赖项,这些参数是在对象实例被构造或从工厂方法返回后在对象实例上配置的。然后,容器的工作是在创建bean时实际注入这些依赖项。即由IoC容器帮对象找相应的依赖对象并注入,而不是由对象主动去找,因此称为控制反转(IoC)。

setter 注入

通过调用无参数构造函数或无参数静态工厂方法以实例化bean之后,在bean上调用setter方法,可以实现基于setterDI

public class TestSetterDI {

DemoBean demoBean = null;

public void setDemoBean(DemoBean demoBean) {
this.demoBean = demoBean;
}
}

构造方法注入

基于构造函数的DI是通过调用具有多个参数(每个参数代表一个对象实例)的构造函数来实现的。另外,调用带有特定参数的静态工厂方法来构造Bean几乎是等效的,本文的其余部分将类似地考虑构造函数的参数和静态工厂方法的参数。

public class ConstructorDI {

DemoBean demoBean = null;

public TestSetterDI (DemoBean demoBean) {
this.demoBean = demoBean;
}
}

注解注入

注解注入只需要在需要在成员变量上添加@Autowire注解即可

public class ConstructorDI {

@Autowire
private DemoBean demoBean;
}
}

spring面试题

组件和服务之间有什么区别?

组件是一组软件,这些组件将被其它应用程序所使用,且不会进行任何更改。所谓“不更改”是指使用应用程序不会更改组件的源代码,尽管它们可以通过组件作者允许的方式扩展组件来更改组件的行为。

服务与组件相似,供外部应用程序使用。主要的区别在于本地使用的组件(比如jar文件、程序集、dll或源导入)。服务将通过同步或异步的某个远程接口(例如,Web服务,消息系统,RPC或套接字)远程使用。

DI与服务定位器模式有何不同?

依赖项注入器的主要好处是,它允许根据环境和使用情况注入合适的服务实现。注入不是打破这种依赖性的唯一方法,另一种方法是使用服务定位器。服务定位器的基本思想是拥有一个对象,该对象知道如何掌握应用程序可能需要的所有服务。然后,它将扫描所有此类服务,并将它们存储为单例注册表中。当要求提供服务实现时,请求者可以使用令牌查询注册表并获取适当的实现。

通常,这些注册表是通过一些配置文件填充的。关键区别在于,使用服务定位器时,服务的每个用户都对定位器具有依赖性。定位器可以隐藏对其他实现的依赖关系,但是还是需要查看定位器。

使用哪个更好的服务(即服务定位器或依赖项注入)?

正如上文已经说过的,关键区别在于,使用服务定位器,服务的每个用户都对定位器有依赖性。这意味着必须在输入和输出方面了解服务定位器的详细信息。因此,实际上成为选择哪种模式的决定因素。

如果维护注册表信息既简单又必要,则可以使用服务定位器,或者直接使用依赖注入,因为它对服务的使用者是无感知的

构造函数注入或setter或注解注入哪个更好?

基于constructor的注入,会固定依赖注入的顺序;该方式不允许我们创建bean对象之间的循环依赖关系,这种限制其实是一种利用构造器来注入的益处 - 当你甚至没有注意到使用setter注入的时候,Spring能解决循环依赖的问题;

基于setter的注入,只有当对象是需要被注入的时候它才会帮助我们注入依赖,而不是在初始化的时候就注入;另一方面如果你使用基于constructor注入,CGLIB不能创建一个代理,迫使你使用基于接口的代理或虚拟的无参数构造函数。

我的偏好是注解注入,这种方式看起来非常好,精短,可读性高,不需要多余的代码,也方便维护;

什么是BeanFactory ?

BeanFactory就像一个工厂类,其中包含一系列beanBeanFactory在其内部保存多个BeanBean定义,然后在客户要求时实例化Bean

BeanFactory能够在实例化协作对象之间创建关联。这消除了bean本身和bean客户端的配置负担。BeanFactory还参与bean的生命周期,从而调用自定义初始化和销毁​​方法。

什么是ApplicationContext ?

Bean工厂适合简单的应用程序,但是要利用Spring框架的全部功能,您可能需要升级到Spring更高级的容器即应用程序上下文。从表面上看,应用程序上下文与Bean工厂相同,两者都加载Bean定义,将Bean绑定在一起并根据请求分配Bean。但它也提供如下功能:

  • 解决文本消息的方法,包括对国际化的支持。
  • 加载文件资源的通用方法。
  • bean注册监听器的事件。

ApplicationContext的常见的实现有哪些 ?

ApplicationContext的三种常用实现是:

  1. ClassPathXmlApplicationContext:它从位于类路径中的XML文件中加载上下文定义,并将上下文定义视为类路径资源。使用代码从应用程序的类路径中加载应用程序上下文。
    ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
    
    
  2. FileSystemXmlApplicationContext:它从文件系统中的XML文件加载上下文定义。使用代码从文件系统中加载应用程序上下文。
ApplicationContext context = new FileSystemXmlApplicationContext("bean.xml");
  1. XmlWebApplicationContext:它从Web应用程序中包含的XML文件中加载上下文定义。

BeanFactory或ApplicationContext最好使用哪个 ?

BeanFactory基本上只是实例化和配置BeanApplicationContext也可以做到这一点,它提供了支持基础设施来支持许多企业特有的特性,例如事务和AOP

因此,建议使用ApplicationContext

在本教程中,我们在spring学习了iocdi之间的区别。


Spring系列三:IoC 与 DI的更多相关文章

  1. Spring系列(1)--IOC 和 DI

    IOC 和 DI IOC 原理 xml 配置文件配置 bean dom4j 读取配置文件 工厂设计模式 反射机制创建对象 applicationContext.xml 配置文件,该配置文件名可自定义: ...

  2. Spring系列之IOC的原理及手动实现

    目录 Spring系列之IOC的原理及手动实现 Spring系列之DI的原理及手动实现 导语 Spring是一个分层的JavaSE/EE full-stack(一站式) 轻量级开源框架.也是几乎所有J ...

  3. 用IDEA详解Spring中的IoC和DI(挺透彻的,点进来看看吧)

    用IDEA详解Spring中的IoC和DI 一.Spring IoC的基本概念 控制反转(IoC)是一个比较抽象的概念,它主要用来消减计算机程序的耦合问题,是Spring框架的核心.依赖注入(DI)是 ...

  4. Spring核心思想——IOC和DI

    基本概念 IOC是什么?     IOC(Inversion of Control)控制反转,IOC是一种新的Java编程模式,目前很多轻量级容器都在广泛使用的模式. IOC解决了什么问题?      ...

  5. 初识Spring框架实现IOC和DI(依赖注入)

    学习过Spring框架的人一定都会听过Spring的IoC(控制反转) .DI(依赖注入)这两个概念,对于初学Spring的人来说,总觉得IoC .DI这两个概念是模糊不清的,是很难理解的, IoC是 ...

  6. Spring自学教程-IOC、DI、AOP(二)

    一.spring的IOC-就是怎样使用spring来创建对象 二.springDI(依赖注入)-就是怎样给属性赋值 通过set方式赋值 以下我们只需要记住两点的赋值,基本类型和引用类型的赋值 基本类型 ...

  7. Spring 简单使用IoC与DI——XML配置

    目录 Spring简介 导入jar包 Spring配置文件 Spring的IoC IoC简介 快速使用IoC Spring创建对象的三种方式 使用构造方法 使用实例工厂 使用静态静态工厂 Spring ...

  8. 理解Spring中的IoC和DI

    什么是IoC和DI IoC(Inversion of Control 控制反转):是一种面向对象编程中的一种设计原则,用来减低计算机代码之间的耦合度.其基本思想是:借助于"第三方" ...

  9. 学习Spring5必知必会(3)~Spring的核心 IoC 和 DI

    一.Spring的核心 IoC(基于XML) 1.IoC容器 (1)BeanFactory容器创建对象: //使用BeanFactory @Test void testBeanFactory() th ...

随机推荐

  1. luogu2634

    P2634 [国家集训队]聪聪可可 题目描述 聪聪和可可是兄弟俩,他们俩经常为了一些琐事打起来,例如家中只剩下最后一根冰棍而两人都想吃.两个人都想玩儿电脑(可是他们家只有一台电脑)……遇到这种问题,一 ...

  2. Django基础之Session操作

    1. 创建一个示例 1.1 第一步 首先创建一个django项目,创建app01, 连接数据库,做好准备工作. 然后在templates目录下创建两个html: login.html负责登录页面: b ...

  3. 浏览器事件循环机制(event loop)

    JS是单线程的 JS是单线程的,或者说只有一个主线程,也就是它一次只能执行一段代码.JS中其实是没有线程概念的,所谓的单线程也只是相对于多线程而言.JS的设计初衷就没有考虑这些,针对JS这种不具备并行 ...

  4. python基本数据类型剖析

    一. 基本数据类型常用功能:1. 整数 int #int内部优化 n1=123 n2=n1 n1= 123 n2= 123 ========2份内存========= if -5~257: n1= 1 ...

  5. Shichikuji and Power Grid

    D. Shichikuji and Power Grid 参考:Codeforces Round #597 (Div. 2) 思路:一个很裸的最小生成树.把建立基站看成是,城市与源点(虚构的)建边.由 ...

  6. Codeforces 959D. Mahmoud and Ehab and another array construction task(构造, 简单数论)

    Codeforces 959D. Mahmoud and Ehab and another array construction task 题意 构造一个任意两个数都互质的序列,使其字典序大等于a序列 ...

  7. 微信小程序底层原理与运行机制类文章学习

    参考文档 小程序底层实现原理及一些思考 为了安全和管控, 双线程执行 Web Worker执行用户的代码; UI线程执行大部分的功能. 微信小程序架构原理 只通过mvvm模板语法动态改变页面, 不支持 ...

  8. js动态往对象里边添加一项

    第一种方法let obj ={"name":"tom","age":16}let key = "id";let valu ...

  9. 微信小程序 保存图片

    微信小程序 保存图片 注: 此处使用的是小程序 wepy框架, 原生或其他的请注意转换写法 <div class="handle"> <button class= ...

  10. tkinter入门-按钮的基本属性

    1.  尺寸的大小  ipadx 和 ipady import tkinter root = tkinter.Tk() root.minsize(500, 500) # 基本属性 # 按钮组件 # 绝 ...