Spring IoC是什么

2023-11-16

 IoC是什么

Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想。在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。如何理解好Ioc呢?理解好Ioc的关键是要明确“谁控制谁,控制什么,为何是反转(有反转就应该有正转了),哪些方面反转了”,那我们来深入分析一下:

 

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

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

用图例说明一下,传统程序设计如图2-1,都是主动去创建相关对象然后再组合起来:

 

图2-1 传统应用程序示意图

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

 

图2-2有IoC/DI容器后程序结构示意图

 

1.1.2  IoC能做什么

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

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

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

 

2.1.3  IoC和DI

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

 

理解DI的关键是:“谁依赖谁,为什么需要依赖,谁注入谁,注入了什么”,那我们来深入分析一下:

 

谁依赖于谁:当然是应用程序依赖于IoC容器;

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

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

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

 

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

 

注:如果想要更加深入的了解IoC和DI,请参考大师级人物Martin Fowler的一篇经典文章《Inversion of Control Containers and the Dependency Injection pattern》,原文地址:http://www.martinfowler.com/articles/injection.html。

 

 

IOC容器就是具有依赖注入功能的容器,IOC容器负责实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。应用程序无需在代码中new相关的对象,应用程序由IOC容器进行组装。

spring IOC管理的对象,我们称为bean。bean就是spring容器初始化,装配,及管理的对象,除此之外,bean就与应用程序中的其他对象没有什么区别。那IOC如何实例化bean、管理bean之间的依赖关系?这些就需要配置元数据。

写个hello world(我用的是maven)

pom.xml

<dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>4.3.4.RELEASE</version>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.11</version>
      <scope>test</scope>
    </dependency>
    <dependency>
    <groupId>jdom</groupId>
    <artifactId>jdom</artifactId>
    <version>1.1</version>
</dependency>

helloInter.java

public interface helloInter {
           public void sayHello();  
}

helloImpl.java

public class helloImpl implements helloInter{

    public void sayHello() {
        // TODO Auto-generated method stub
        System.out.println("Hello World!!!");
    }

}

hello.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" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans-4.0.xsd  
    http://www.springframework.org/schema/context                http://www.springframework.org/schema/context/spring-context-4.0.xsd">
    <!-- id 表示你这个组件的名字,class表示组件类 -->
    <bean id="hello" class="com.lj.testspring.chapter.helloImpl"></bean>
</beans>  

helloTest.java

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;


public class helloTest {
           @Test
           public void testHelloWorld() {  
                 //1、读取配置文件实例化一个IoC容器  
                 ApplicationContext context = new ClassPathXmlApplicationContext("hello.xml");  
                 //2、从容器中获取Bean,注意此处完全“面向接口编程,而不是面向实现”  
                 helloInter helloApi = context.getBean("hello", helloInter.class);  
                  //3、执行业务逻辑  
                  helloApi.sayHello();  
           }  

}

运行,可以看出输出一个hello World。

在spring IOC容器的代表就是org.springframework.beans包中的BeanFactory接口,BeanFactory接口提供了IOC容器最基本功能,而org.springframework.context包下的ApplicationContext接口扩展了BeanFactory,还提供了与Spring AOP集成,国际化处理,事件传播及提供不同层次的context实现。简单说,BeanFactory提供了IOC容器最基本功能,而ApplicationContext则增加了更多支持企业级功能支持。ApplicationContext完全继承BeanFactory,因而BeanFactory所具有的语义也适用于ApplicationContext。

容器实现一览:

XmlBeanFactory:BeanFactory实现,提供基本的IoC容器功能,可以从classpath或文件系统等获取资源;
(1) File file = new File("fileSystemConfig.xml");
Resource resource = new FileSystemResource(file);
BeanFactory beanFactory = new XmlBeanFactory(resource);
(2)
Resource resource = new ClassPathResource("classpath.xml");
BeanFactory beanFactory = new XmlBeanFactory(resource);

ClassPathXmlApplicationContext:ApplicationContext实现,从classpath获取配置文件;
BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath.xml");

FileSystemXmlApplicationContext:ApplicationContext实现,从文件系统获取配置文件。
BeanFactory beanFactory = new FileSystemXmlApplicationContext("fileSystemConfig.xml");

 

ApplicationContext接口获取Bean方法简介:
• Object getBean(String name) 根据名称返回一个Bean,客户端需要自己进行类型转换;
• T getBean(String name, Class<T> requiredType) 根据名称和指定的类型返回一个Bean,客户端无需自己进行类型转换,如果类型转换失败,容器抛出异常;

• T getBean(Class<T> requiredType) 根据指定的类型返回一个Bean,客户端无需自己进行类型转换,如果没有或有
多于一个Bean存在容器将抛出异常;
• Map<String, T> getBeansOfType(Class<T> type) 根据指定的类型返回一个键值为名字和值为Bean对象的 Map,
如果没有Bean对象存在则返回空的Map。

 

让我们来看下IoC容器到底是如何工作。在此我们以xml配置方式来分析一下:

一、准备配置文件:就像前边Hello World配置文件一样,在配置文件中声明Bean定义也就是为Bean配置元数据。

二、由IoC容器进行解析元数据: IoC容器的Bean Reader读取并解析配置文件,根据定义生成BeanDefinition配置元数据对象,IoC容器根据BeanDefinition进行实例化、配置及组装Bean。

三、实例化IoC容器:由客户端实例化容器,获取需要的Bean。

 
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring IoC是什么 的相关文章

  • 爬虫-Xpath-数据提取

    Xpath数据提取 xpath基本介绍和使用 xpath中常用的获取节点的表达式 xpath中常用的获取特定节点的表达式 XPath XML Path Language 是一门在 HTML XML 文档中查找信息的 语言 可用来在 HTML
  • return _compile(pattern, flags).search(string) TypeError: expected string or bytes-like object

    今天使用正则处理excel的数据时 报了一个错误 记录一下处理的方法 一开始去查了下报错 但是大多别人的答案却不能够解决我的问题 该错误的意思是 类型错误 期望的字符串或字节类对象 那就是我使用正则的数据有问题 我查看了下我的数据类型 果然
  • 容器云技术选择之kubernetes和swarm对比

    swarm和k8s本质都是容器编排服务 它们都能把底层的宿主机抽象化 然后将应用从以构建好的镜像开始 最终以docker的方式部署到宿主机上 应该选择哪种方案作为我们的容器云服务呢 我觉得k8s kubernetes简称 跟swarm的比较
  • 写出Java爱心代码

    以下是一段简单的Java代码 它用字符画了一个爱心图形 public class Heart public static void main String args System out println System out println
  • 猜数字小游戏(JAVA)

    猜数字小游戏 题目描述 代码 运行效果 新增功能 思路 代码 运行效果 题目描述 猜数字 又称 Bulls and Cows 是一种古老的的密码破译类益智类小游戏 起源于20世纪中期 一般由两个人或多人玩 也可以由一个人和电脑玩 通常由两个
  • 论区块链应用开发中的技术选型

    区块链技术栈总览 区块链技术栈现阶段总览 链端选型 Fabric x 逐渐被市场淘汰 和以太坊不能兼容的链 x 原因 单打独斗 无法借力 FISCO BCOS Venachain 基于 Move 的链 maybe 前端技术栈 React o
  • RobotFramework详细安装教程

    RobotFramework详细安装教程 Robot Framework安装教程 需要安装以下 1 Python2 7以上版本 这里用的是 Python3 8 2 pip 和 setuptools Python 的套件管理程式 最新版的Py
  • Linux中/etc目录下passwd、shadow、group、gshadow文件解释

    Linux用户和用户组管理 etc目录解释 1 Linux etc passwd内容解释 2 Linux etc shadow 影子文件 内容解析 3 Linux etc group文件解析 4 Linux etc gshadow文件内容解
  • js中this指向问题

    1 概念 函数中的this指向 非严格模式下this指向全局变量window 严格模式下this为undefined 对象中的this指向 指向该对象本身 类中的this指向 指向该对象的实例对象 this指向的修改问题 2 函数中的thi
  • 【ES6】中var、let、const的区别

    一 块级作用域 ES5 中作用域有 全局作用域 函数作用域 ES6 中新增了块级作用域 块级作用域由 包括 if语句和for语句里面的 也属于块级作用域 var a 1 console log a 1 console log a 1 通过v
  • 微信小程序获取用户openid,头像昵称信息,后台java代码

    小程序前端 app js wx login success res gt 发送 res code 到后台换取 openId sessionKey unionId if res code wx getUserInfo success func
  • 池化层的作用

    目录 1 池化层理解 2 池化层的作用 3 函数解析 tf nn max pool value ksize strides padding name None 4 代码演示详解维度变化 1 池化层理解 池化层夹在连续的卷积层中间 用于压缩数
  • 【Python】请编码实现动物世界的继承关系:动物(Animal)具有行为:吃(eat)、睡觉(sleep)动物包括:兔子(Rabbit),老虎(Tiger)动物吃的行为各不相同(兔子吃草,老虎吃肉)

    请编码实现动物世界的继承关系 a 动物 Animal 具有行为 吃 eat 睡觉 sleep b 动物包括 兔子 Rabbit 老虎 Tiger c 这些动物吃的行为各不相同 兔子吃草 老虎吃肉 d 但睡觉的行为是一致的 e 请通过继承实现
  • 求助帖!Robotframework导入selenium2library库后缺少一些关键字,怎么解决

    求助帖 Robotframework导入selenium2library库后缺少一些关键字 怎么解决 找不到Open Browser等一般关键字 安装的版本如下 但是我的site packages中的文件都正常 可就是找不到某些关键字 求助
  • 计算机学感悟,计算机学习感悟

    篇一 计算机学习感悟 浅谈学习 计算机应用基础 的收获与感悟 随着信息技术的快速发展 计算机已成为人们在经济生活 社会 交往和日常生活中不可缺少的工具 是否具有使用计算机的基本技 能 已成为衡量一个人文化素质高低的重要标志之一 上高中的时候
  • 目标检测params,flops计算

    目标检测params flops计算 参数数量用params表示 关系到模型大小 单位通常为M 通常参数用float32表示 所以模型大小是参数数量的4倍 理论计算量用FLOPs或者M Adds表示 这里用FLOPs写起来简单 关系到算法速
  • Java之异常Throwable

    异常Throwable 自定义异常案例 package com week03 Day01 总结 异常 Throwable Error Exception CheckException RuntimeException 编译时异常 1 直接抛
  • mqtt 变为乱码 接受16进制字节流_常见乱码问题分析和总结

    背景概述 在我们的日常工作生活中一定碰到过下面的情况 场景1 安装完某个软件后 看到的安装程序变成类似这样的一组字符 图1所示的样子 图 1 安装程序中的乱码 场景2 打开一个文档发现里面的内容全面是问号 如图2所示 图 2 带有问号的乱码
  • Redis类型之Geospatial

    1 简介 Redis 3 2 中增加了对GEO类型的支持 GEO Geographic 地理信息的缩写 该类型 就是元素的2维坐标 在地图上就是经纬度 redis基于该类型 提供了经纬度设置 查询 范围查询 距离查询 经纬度Hash等常见操

随机推荐

  • locate函数

    include
  • 如何从远程服务器复制文件,远程服务器文件如何复制到本地

    远程服务器文件如何复制到本地 内容精选 换一换 本节为您介绍如何在本机使用远程登录工具MSTSC登录Windows裸金属服务器 裸金属服务器状态必须为 运行中 如果Windows裸金属服务器采用密钥方式鉴权 需要先获取裸金属服务器的密码 获
  • 3D游戏编程与设计作业——游戏智能

    一 作业要求 坦克对战游戏AI设计 从商店下载游戏 Kawaii Tank 或 其他坦克模型 构建AI对战坦克 具体要求 使用 感知 思考 行为 模型 建模 AI 坦克 场景中要放置一些障碍阻挡对手视线 坦克要放置一个矩阵包围盒触发器 保证
  • 如何解决Exception in thread “main” java.sql.SQLException: Statement.executeUpdate() or Statement.execute

    场景 黑马程序员javaweb基础教程 视频jdbc快速入门时出现的报错 问题描述 Exception in thread main java sql SQLException Statement executeUpdate or Stat
  • late_initcall和module_init

    late initcall和module init 分类 linux驱动程序设计 2012 11 04 15 14 3680人阅读 评论 0 收藏 举报 所有的 init函数在区段 initcall init中还保存了一份函数指针 在初始化
  • unittest+ddt自动化测试相关知识点

    unittest是Python单元测试框架 主要分为 测试用例TestCase 一个完整的测试流程 测试套件TestSuite 多个测试用例集合在一起 执行 结果呈现TextTestRunner 用例运行和结果呈现 结果呈现常用HtmlTe
  • 环境配置tips

    一 MySQL在Linux下数据库名 表名 列名 别名大小写规则是这样的 1 数据库名与表名是严格区分大小写的 2 表的别名是严格区分大小写的 3 列名与列的别名在所有的情况下均是忽略大小写的 4 变量名也是严格区分大小写的 修改不区分大小
  • OpenWrt系统无法进入Luci解决办法之一

    当在OpenWrt系统重启后 打开Luci后台时有时可能会遇到以下错误报告 usr lib lua luci dispatcher lua 577 bad argument 1 to pairs table expected got nil
  • cocos2d-x 4.0 版本修改点

    转自 https discuss cocos2d x org t cocos2d x v4 0 released 48487 Features support metal on iOS macOS use CMake for all pla
  • vue : 无法加载文件 \Node.js\node_global\vue.ps1。未对文件 \Node.js\node_global\vue.ps1 进行数字签名。无法在当前系统上运行该脚本。

    vue 无法加载文件 D Node js node global vue ps1 未对文件 D Node js node global vue ps1 进行数字签名 无法在当前系统上运行该脚本 最近在使用powershell下使用 vue
  • pandas的行列获取/pandas iloc和loc的使用/如何获取pandas的行和列

    Pandas行和列的获取 由于平时没有系统的学习pandas 导致在实际应用过程中 对于获取df中的行和列经常出现问题 于是总结一下 供自己以后参考 参考的书籍在线版链接 利用 Python 进行数据分析 第 2 版 0 查看手册 请当你看
  • 深度学习之基于VGG16与ResNet50实现鸟类识别

    鸟类识别在之前做过 但是效果特别差 而且ResNet50的效果直接差到爆炸 这次利用VGG16与ResNet50的官方模型进行鸟类识别 1 导入库 import tensorflow as tf import numpy as np imp
  • ubuntu安装/查看已安装包的方法

    自己折腾ubuntu安装包来着 发现一篇文章非常实用 将apt get和dpkg等命令的参数讲解非常全面 于是转载过来 中文的比英文的帮助看着还是顺手一点 原文链接 http www cnblogs com forward archive
  • vue 给页面局部加水印和全部加水印

    局部加水印 在公共类js下 新建一个watermask js 代码如下 export default tool js addWaterMark const strArr localStorage getItem loginUserName
  • 图的深度优先遍历(Depth First Search)

    图的深度优先遍历 Depth First Search 基本思想 类似于二叉树的先序遍历 假设图中所有结点均未被访问 从初始结点访问 访问其第一个邻接结点 接着以被访问的邻接结点作为初始结点 访问它的第一个邻接结点 递归的过程 算法步骤 访
  • Cesium快速入门

    Cesium是全世界使用最广泛的3D WebGIS引擎 国内有若干个GIS厂家的3D GIS引擎也是基于Cesium进行开发 随着国家 新基建 数字化 战略的不断发展深化 越来越多的城市数字化项目需要用上3D GIS引擎 对Web端而言 C
  • 简单记录搭建SSM(Spring+Spring MVC+Mybatis)整合

    业务层 View 数据显示 Controller 业务控制 执行成功怎么处理 执行失败怎么处理 Service 业务处理 Model 数据库相关实体类 增删改查 工程搭建 第一步 创建Maven web工程 点击finish创建完毕工程 第
  • C++在路径下新建一个指定名称的文件夹

    在保存数据是 我们希望将新生成的数据单独保存在一个文件夹中 其实我们可以通过程序自动生成一个指定名称的文件夹 存放数据 而不必提前手动新建文件夹并修改名称 代码实现的方法也很简单 但是需要注意的是该方法需要包含windows h头文件 代如
  • 树莓派——制作静态库、动态库

    库的特点 库是可执行代码的二进制形式 即将源代码转换成二进制的源代码 相当于对源代码进行了加密 别人可以看见库使用库 但是看不见库的源代码 2种类型库 静态库 libxxx a 动态库 libxxx so 静态库 在程序执行前就加入到目标程
  • Spring IoC是什么

    IoC是什么 Ioc Inversion of Control 即 控制反转 不是什么技术 而是一种设计思想 在Java开发中 Ioc意味着将你设计好的对象交给容器控制 而不是传统的在你的对象内部直接控制 如何理解好Ioc呢 理解好Ioc的