搞透 IOC,Spring IOC 看这篇就够了!

搞透 IOC,Spring IOC 看这篇就够了!

IOCAOP属于Spring的核心内容,如果想掌握好Spring你肯定需要对IOC有足够的了解 @mikechen

IOC的定义

IOC是Inversion of Control的缩写,多数书籍翻译成”控制反转”。

IOC不是一种技术,只是一种思想,一个重要的面向对象编程的法则,它能指导我们如何设计出松耦合、更优良的程序。

传统应用程序都是由我们在类内部主动创建依赖对象,从而导致类与类之间高耦合,难于测试,有了IoC容器后,把创建和查找依赖对象的控制权交给了容器,如下图所示:

搞透 IOC,Spring IOC 看这篇就够了!

上图引入了IOC容器,使得A、B、C、D这4个对象没有了耦合关系,齿轮之间的传动全部依靠”第三方”了,全部对象的控制权全部上缴给”第三方”IOC容器。

所以,IOC借助于”第三方”实现具有依赖关系的对象之间的解耦,使程序更优良。

IOC与DI的关系

其实IOC包括依赖查找(DL)和依赖注入(DI),只不过DL因为有侵入性 (它需要用户自己去是使用 API 进行查找资源和组装对象),已经被抛弃。

所以现在提到IOC,更多的想到的就是依赖注入(DI)了, 如图所示:

搞透 IOC,Spring IOC 看这篇就够了!

DI的全称是Dependency Injection,中文称之为依赖注入,它与控制反转(IOC)的含义相同,只不过这两个称呼是从两个角度描述的同一个概念。

当某个Java对象(调用者)需要调用另一个Java对象(被调用者,即被依赖对象)时,在传统模式下,调用者通常会采用”new 被调用者”的代码方式来创建对象,如图所示:

搞透 IOC,Spring IOC 看这篇就够了!
这种方式会导致调用者与被调用者之间的耦合性增加,不利于后期项目的升级和维护。

在使用Spring框架之后,对象的实例不再由调用者来创建,而是由Spring容器来创建,Spring容器会负责控制程序之间的关系,而不是由调用者的程序代码直接控制。

这样,控制权由应用代码转到了Spring容器,控制权发生了反转,这就是Spring的控制反转IOC。

从Spring容器的角度来看,Spring容器负责将被依赖对象赋值给调用者的成员变量,这相当于为调用者注入了它依赖的实例,这就是Spring的依赖注入,如图所示:

搞透 IOC,Spring IOC 看这篇就够了!

依赖注入方式

Spring的依赖注入,我们一般使用@Autowired注解来完成,关于依赖注入一般有三种方式:

属性注入、构造器注入、setter方法注入:

1.属性注入

属性注入是大家最为常见也是使用最多的一种注入方式了,代码如下:

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserMapper userMapper;

    //...

}

2.Set注入

set 方法注入太过于臃肿,实际上很少使用:

@Service
public class UserServiceImpl implements UserService {
    private UserMapper userMapper;
    @Autowired
    public void setUserMapper(UserMapper userMapper) {
        this.userMapper = userMapper;
    }
}

3.构造器注入

构造器注入是官方推荐的方式,如下:

@Service
public class UserServiceImpl implements UserService {
    private final UserMapper userMapper;

    @Autowired
    public UserServiceImpl(UserMapper userMapper) {
        this.userMapper = userMapper;
    }
}

IOC的优缺点

IOC的优点

实现组件之间的解耦,提高程序的灵活性和可维护性。

IOC的缺点

使用IOC框架产品能够给我们的开发过程带来很大的好处,但是也要充分认识引入IOC框架的缺点,做到心中有数。

  1. 生成一个对象的步骤变复杂了(其实上操作上还是挺简单的),对于不习惯这种方式的人,会觉得有些别扭和不直观。
  2. 对象 生成因为是使用反射编程,在效率上有些损耗,但相对于IoC提高的维护性和灵活性来说,这点损耗是微不足道的,除非某对象的生成对效率要求特别高。

IOC的实现原理

IOC容器其实就是一个大工厂,它用来管理我们所有的对象以及依赖关系。

  • 原理就是通过 Java 的反射技术来实现的,通过反射我们可以获取类的所有信息(成员变量、类名等等等);
  • 再通过配置文件(xml)或者注解来描述类与类之间的关系。

这样我们就可以通过这些配置信息和反射技术来构建出对应的对象和依赖关系了,如下图所示:

搞透 IOC,Spring IOC 看这篇就够了!

IOC容器和对象的创建过程如下:

1.先创建BeanFactory容器

2.加载配置文件,封装成BeanDefinition

3.调用执行BeanFactoryPostprocessor

  • 准备工作;
  • 准备BeanPostProcessor;
  • 准备监听器、事件、广播器;

4.实例化

5.初始化

6.获取到完整对象。

以上

作者简介

陈睿|mikechen,10年+大厂架构经验,《BAT架构技术500期》系列文章作者,专注于互联网架构技术。

阅读mikechen的互联网架构更多技术文章合集

Java并发|JVM|MySQL|Spring|Redis|分布式|高并发

Original: https://www.cnblogs.com/mikechenshare/p/16729871.html
Author: mikechen的互联网架构
Title: 搞透 IOC,Spring IOC 看这篇就够了!

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/616794/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Java后端代码规范与优化建议

    1、尽量指定类、方法的final修饰符 带有final修饰符的类是不可派生的。在Java核心API中,有许多应用final的例子,例如java.lang.String,整个类都是f…

    Java 2023年5月29日
    058
  • Java定时器Timer和TimerTask

    方式一:设定指定任务task在指定时间time执行 schedule(TimerTask task, Date date) public static void main (Str…

    Java 2023年6月15日
    076
  • JavaScript基础知识

    undefined window.alert() –写入警告框 document.write()—写入HTML输出 console.log()—写入浏览器控制台 aler…

    Java 2023年6月5日
    075
  • 3.MySQL常用知识

    1,基础查询 //1.group by+ 聚合函数+ HAVING条&…

    Java 2023年6月13日
    074
  • 面试题:Java中为什么只有值传递?

    作者:小牛呼噜噜 | https://xiaoniuhululu.com计算机内功、JAVA底层、面试相关资料等更多精彩文章在公众号「小牛呼噜噜 」 经典的问题 形参&实参…

    Java 2023年6月15日
    085
  • Kafka 基础概念及架构

    一、Kafka 介绍 Kafka是⼀个分布式、分区的、多副本的、多⽣产者、多订阅者,基于zookeeper协调的分布式⽇志系统(也可以当做MQ系统),常⻅可以⽤于web/nginx…

    Java 2023年6月5日
    089
  • NLP中的语言模型预训练相关总结

    NLP中的语言模型预训练相关总结 NLP中的语言模型预训练相关总结 前言 one-hot 模型 word2vec模型 ELMO模型 Open AT GPT Bert 总结 参考资料…

    Java 2023年6月7日
    051
  • 一文了解Flink State Backends

    当我们使用Flink进行流式计算时,通常会产生各种形式的中间结果,我们称之为State。有状态产生,就必然涉及到状态的存储,那么Flink中定义了哪些形式的状态存储呢,下面一一给大…

    Java 2023年6月6日
    063
  • SpringBoot Aop打印参数

    import java.util.Enumeration; import javax.servlet.http.HttpServletRequest; import lombok….

    Java 2023年5月30日
    059
  • 自定义视图(组合控件)

    前言 Android自定义控件主要分为两种,一种是通过继承View来实现自定义控件,另一种是通过组合已有到控件来实现自定义控件,上篇文章自定义视图(继承View)我们介绍了下继承V…

    Java 2023年6月7日
    080
  • CAS 入门实战(4)–自定义登录页面

    CAS 默认的登录页面显然不适合实际的使用,本文主要介绍如何自定义登录页面;文中使用到的软件版本:JDK 1.8.0_191、Tomcat 8.5.76、CAS 5.3.16。 1…

    Java 2023年6月16日
    078
  • Mybatis完整版详解

    一、简介 1.什么是MyBatis MyBatis 是一款优秀的持久层框架 它支持自定义 SQL、存储过程以及高级映射。 MyBatis 免除了几乎所有的 JDBC 代码以及设置参…

    Java 2023年6月14日
    054
  • Java Class 文件中Method的存储

    class文件是java编译后的文件类型。其代表一个类,其有专门的存储格式。其中会存放数据也会存放方法,而所谓的方法存放就是将方法中的调用都转换成java字节码指令。所方法调用从机…

    Java 2023年5月29日
    083
  • Java I/O 流之对象流中的序列化和反序列化

    一、概念 当两个进程远程通信时,彼此可以发送各种类型的数据。 无论是何种类型的数据,都会以二进制序列的形式在网络上传送。比如,我们可以通过 http 协议发送字符串信息;我们也可以…

    Java 2023年6月13日
    072
  • mongodb添加延时节点

    简介 延时节点是主节点过去某个时间点的”数据快照”,通常用来做数据备份,如果主节点有误操作而删除了数据,可以通过延时节点来恢复数据。例如,当前时间是10:0…

    Java 2023年6月6日
    057
  • 使用MongoDB做评论的原因是什么?

    1.加载大量低价值的业务数据 数据量大 但自身价值比较低 。 例如我们更多的是关注文章本身内容 而不是数据量庞大的评论内容 2.评论的读写操作频繁 查询评论和发表评论 3.又因为评…

    Java 2023年6月6日
    070
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球