Java Spring 控制反转(IOC)容器详解

 更新时间:2021年10月04日 14:26:36   作者:JD强子  
这篇文章主要为大家详细介绍了Spring控制反转IoC入门使用的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

IoC 容器是 Spring 的核心,也可以称为 Spring 容器。Spring 通过 IoC 容器来管理对象的实例化和初始化,以及对象从创建到销毁的整个生命周期。

Spring 中使用的对象都由 IoC 容器管理,不需要我们手动使用 new 运算符创建对象。由 IoC 容器管理的对象称为 Spring Bean,Spring Bean 就是 Java 对象,和使用 new 运算符创建的对象没有区别。

Spring 通过读取 XML 或 Java 注解中的信息来获取哪些对象需要实例化。

Spring 提供 2 种不同类型的 IoC 容器,即 BeanFactory 和 ApplicationContext 容器。

什么是容器?

容器是一种为某种特定组件的运行提供必要支持的一个软件环境。例如,Tomcat就是一个Servlet容器,它可以为Servlet的运行提供运行环境。类似Docker这样的软件也是一个容器,它提供了必要的Linux环境以便运行一个特定的Linux进程。

通常来说,使用容器运行组件,除了提供一个组件运行环境之外,容器还提供了许多底层服务。例如,Servlet容器底层实现了TCP连接,解析HTTP协议等非常复杂的服务,如果没有容器来提供这些服务,我们就无法编写像Servlet这样代码简单,功能强大的组件。早期的JavaEE服务器提供的EJB容器最重要的功能就是通过声明式事务服务,使得EJB组件的开发人员不必自己编写冗长的事务处理代码,所以极大地简化了事务处理。

无侵入容器

在设计上,Spring的IoC容器是一个高度可扩展的无侵入容器。所谓无侵入,是指应用程序的组件无需实现Spring的特定接口,或者说,组件根本不知道自己在Spring的容器中运行。这种无侵入的设计有以下好处:

1.应用程序组件既可以在Spring的IoC容器中运行,也可以自己编写代码自行组装配置;

2.测试的时候并不依赖Spring容器,可单独进行测试,大大提高了开发效率。

IOC控制反转

Spring提供的容器又称为IoC容器,什么是IoC?

Ioc—Inversion of Control,即“控制反转”,不是什么技术,是一个概念,是一种思想。指将传统上由程序代 码直接操控的对象调用权交给容器,通过容器来实现对象的装配和管理。控制反转就是对对象控制权的转移,从程序代码本身反转到了外部容器。通过容器实现对象的装配和管理。通俗点讲,将对象的创建权交给spring,我们需要new对象,则由spring帮我们创建,然后供我们使用。

那么必然的我们需要创建一个容器,同时需要一种描述来让容器知道需要创建的对象与对象的关系。这个描述最具体表现就是我们可配置的文件。IoC的实质是如何管理对象,传统意义上我们使用new方式来创建对象,但在企业应用开发的过程中,大量的对象创建都在程序中维护很容易造成资源浪费,并且不利于程序的扩展。

其实现方式多种多样。当前比较流行的实现方式是依赖 注入。应用广泛。

依赖:classA 类中含有 classB 的实例,在 classA 中调用 classB 的方法完成功能,即 classA 对 classB 有依赖。

IOC理论推导

传统应用程序开发的弊端

在理解IoC之前,我们先看看通常的Java组件是如何协作的。

我们先用我们原来的方式写一段代码 .

1、先写一个UserDao接口

在这里插入图片描述

2、再去写Dao的实现类

public class UserDaoOneImpl implements UserDao {
   @Override
   public void getUser() {
       System.out.println("One获取用户数据");
  }
}

3、然后去写UserService的接口

在这里插入图片描述

4、最后写Service的实现类

在这里插入图片描述

5、测试一下

在这里插入图片描述

6、再回到UserDao接口

在这里插入图片描述

把Userdao的实现类增加一个 .

public class UserDaoMyTwoImpl implements UserDao {
   @Override
   public void getUser() {
       System.out.println("Two获取用户数据");
  }
}

7、我们就需要去service实现类里面修改对应的实现

public class UserServiceImpl implements UserService {
   private UserDao userDao = new UserDaoTwo();
   @Override
   public void getUser() {
       userDao.getUser();
  }
}

在假设, 我们再增加一个Userdao的实现类 .

public class UserDaoThreeImpl implements UserDao {
   @Override
   public void getUser() {
       System.out.println("Three获取用户数据");
  }
}

那么我们要使用Three , 又需要去service实现类里面修改对应的实现 . 假设我们的这种需求非常大 , 这种方式就根本不适用了, 甚至反人类对吧 , 每次变动 , 都需要修改大量代码 . 这种设计的耦合性太高了, 牵一发而动全身 .

“注入”机制

注入应用程序某个对象,应用程序依赖的对象

依赖注入可以通过set()方法实现。但依赖注入也可以通过构造方法实现。Spring的IoC容器同时支持属性注入和构造方法注入,并允许混合使用。

我们可以在需要用到他的地方 , 不去实现它 , 而是留出一个接口 , 利用set , 我们去代码里修改下 .

在这里插入图片描述

@Test
public void test(){
   UserServiceImpl service = new UserServiceImpl();
   service.setUserDao( new UserDaoTwoImpl() );
   service.getUser();
   //那我们现在又想添加Three去实现呢
   service.setUserDao( new UserDaoThreeImpl() );
   service.getUser();
}

以前所有东西都是由程序去进行控制创建 , 而现在是由我们自行控制创建对象 , 把主动权交给了调用者 . 程序不用去管怎么创建,怎么实现了 . 它只负责提供一个接口 .

这种思想 , 从本质上解决了问题 , 我们程序员不再去管理对象的创建了 , 更多的去关注业务的实现 . 耦合性大大降低 . 这也就是IOC的原型 !

小结

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

在这里插入图片描述

没有什么是加一层解决不了的

在这里插入图片描述

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

IOC本质

IoC是Spring框架的核心内容,使用多种方式完美的实现了IoC,可以使用XML配置,也可以使用注解,新版本的Spring也可以零配置实现IoC。

Spring容器在初始化时先读取配置文件,根据配置文件或元数据创建与组织对象存入容器中,程序使用时再从Ioc容器中取出需要的对象。

在这里插入图片描述

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

DI(依赖注入)

IoC的一个重点是在系统运行中,动态的向某个对象提供它所需要的其他对象。这一点是通过DI(Dependency Injection,依赖注入)来实现的。 比如对象A需要操作数据库,以前我们总是要在A中自己编写代码来获得一个Connection对象,有了 spring我们就只需要告诉spring,A中需要一个Connection,至于这个Connection怎么构造,何时构造,A不需要知道。在系统运行时,spring会在适当的时候制造一个Connection,然后像打针一样,注射到A当中,这样就完成了对各个对象之间关系的控制。A需要依赖 Connection才能正常运行,而这个Connection是由spring注入到A中的,依赖注入的名字就这么来的。那么DI是如何实现的呢? Java 1.3之后一个重要特征是反射(reflection),它允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性,spring就是通过反射来实现注入的。

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注脚本之家的更多内容!

相关文章

  • 对Mapper 中几种update的区别说明

    对Mapper 中几种update的区别说明

    这篇文章主要介绍了对Mapper 中几种update的区别说明,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-11-11
  • Java线程安全中的单例模式

    Java线程安全中的单例模式

    这篇文章主要介绍了Java线程安全中的单例模式,需要的朋友可以参考下
    2015-02-02
  • 利用Java计算某个日期是星期几

    利用Java计算某个日期是星期几

    不知道大家有没有遇到过同样的问题,谁谁的生日又要到了,看看是星期几?每年都要遇到好几次,所以想索性利用Java写个小工具,一次查询某具体日期在n年中分别是星期几。这样不就方便了吗?本文里给出了详细的示例代码,感兴趣的朋友们下面来一起看看吧。
    2016-10-10
  • Java编写程序之输入一个数字实现该数字阶乘的计算

    Java编写程序之输入一个数字实现该数字阶乘的计算

    这篇文章主要介绍了Java编写程序之输入一个数字实现该数字阶乘的计算,本文通过实例代码给大家介绍的非常想详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-02-02
  • 解决springboot服务启动报错:Unable to start embedded contain

    解决springboot服务启动报错:Unable to start embedded contain

    这篇文章主要介绍了解决springboot服务启动报错:Unable to start embedded contain的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • SpringBoot雪花算法主键ID传到前端后精度丢失问题的解决

    SpringBoot雪花算法主键ID传到前端后精度丢失问题的解决

    本文主要介绍了SpringBoot雪花算法主键ID传到前端后精度丢失问题的解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-08-08
  • Mybatis-plus apply函数使用场景分析

    Mybatis-plus apply函数使用场景分析

    Mybatis-plus 里面的 apply方法 是用于拼接自定义的条件判断,自定义时间查询,根据传进来的开始日期,查询所有该日期是数据,但是数据库中保存是时间,所以需要使用apply查询方式并格式化,这篇文章给大家介绍Mybatis-plus apply函数使用,感兴趣的朋友一起看看吧
    2024-02-02
  • 关于@Component注解下的类无法@Autowired问题

    关于@Component注解下的类无法@Autowired问题

    这篇文章主要介绍了关于@Component注解下的类无法@Autowired问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03
  • java识别一篇文章中某单词出现个数的方法

    java识别一篇文章中某单词出现个数的方法

    这篇文章主要介绍了java识别一篇文章中某单词出现个数的方法,涉及java字符解析操作的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-10-10
  • mybatis中resulthandler的用法

    mybatis中resulthandler的用法

    这篇文章主要介绍了mybatis中resulthandler的用法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-01-01

最新评论