您现在的位置是:首页 >技术教程 >Spring ( 三 ) SpringIoC网站首页技术教程

Spring ( 三 ) SpringIoC

春哥的魔法书 2024-06-17 10:15:01
简介Spring ( 三 ) SpringIoC

3.SpringIoC

Spring 核心 是 通过IoC 降低 项目中的类之间的耦合

IoC Inversion of Control 控制反转:
应用本身不负责依赖对象的创建及维护,依赖对象的创建及维护是由外部容器负责的。

​ 这样控制权就由应用转移到了外部容器,控制权的转移就是所谓反转。

DI Dependency Injection依赖注入:
在运行期,由外部容器动态的将依赖对象注入到组件内部中。

在这里插入图片描述

主要分成两个步骤:

​ 先将 类 注册到 SpringIoC 容器上, 也就由SpringIoC容器来管理Bean

​ 再根据 业务需求, 通过SpringIoC容器来搭建类对象之间的关系 , 也就是 依赖注入

3.0.准备

3.0.1.Maven导入依赖

    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.3.6</version>
    </dependency>

由于 Maven 可以自动关联依赖, 依赖结构图

在这里插入图片描述

3.0.2.添加配置文件

在 maven项目的 resources 文件夹中添加 Spring配置文件

右键菜单选择 New > XML Configuration File > Spring config

在这里插入图片描述

填写文件名 spring-config

在这里插入图片描述

打开文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       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">
</beans>

3.1.配置文件方式

3.1.1.声明Bean

在 配置文件中 增加<bean>结点, 用于 将类 注册到SpringIoC容器中

id 是 注册到SpringIoC容器时的别名

class 是 类的实际路径

    <bean id="hw" class="com.yuan.spring.beans.HouWang"  ></bean>

	<bean id="hhr" class="com.yuan.spring.beans.HongHair"></bean>
    <bean id="tsgz" class="com.yuan.spring.beans.TieShanGongZhu"></bean>
    <bean id="nmw" class="com.yuan.spring.beans.NiuMoWang"></bean>

3.1.2.IoC容器

Spring框架的IoC容器(Inversion of Control控制反转容器),是Spring框架的核心组件之一,其作用是管理Spring应用程序中的Java对象,也可称为Bean容器

容器负责在应用程序启动时实例化所有的Bean,并负责将它们注入到其他Bean中,从而实现依赖注入(DI)。

简单来说,Spring IoC容器就是一个集中管理和维护Java对象的容器,可以通过IoC容器将对象的创建和管理过程转移到Spring容器中进行,以达到解耦的目的。

Spring IoC容器主要有两种实现方式:BeanFactoryApplicationContext

BeanFactory是最基本的IoC容器,它只提供了对象的实例化和依赖注入等最基本的功能。而ApplicationContext则是在BeanFactory的基础上做了更多的扩展,提供了更多的企业级特性,例如AOP、国际化和事件传播等功能。

Spring IoC容器使用XML配置文件或注解来描述Bean之间的依赖关系和属性值的设定,并且可以通过配置文件或代码设置不同的Bean作用域(如 Singleton、Prototype等)以及生命周期的管理。

容器在启动时会读取这些配置信息,并根据配置信息实例化Bean并维护它们的依赖关系,当某个Bean被需要时,容器会根据配置信息将对应的Bean返回给调用方。

在这里插入图片描述

3.1.2.1.根据 编译路径下的 配置文件 生成 IoC 容器

// ClassPath 编译路径   Xml 文件格式  
AbstractApplicationContext beanFactory = new ClassPathXmlApplicationContext("spring-config.xml");

3.1.2.2.根据 文件物理路径下的 配置文件 生成IoC 容器

// FileSystem 文件系统 Xml 文件格式
AbstractApplicationContext beanFactoryFile = new FileSystemXmlApplicationContext("D:\spring-config.xml");

3.1.3.得到实例

从SpringIoC 中得到 类的实例对象

// 根据配置文件中 注册的id 得到 类的实例对象实例
// 这种方式返回Object类型 要强制转形
HouWang hw = (HouWang) beanFactory.getBean("hw");

// 根据配置文件中 注册的class类型 得到 类的实例对象实例
HouWang houWang = beanFactory.getBean(HouWang.class);

3.1.4.作用域

Spring IoC 容器中的对象都有作用域(Scope)指定了 Bean 实例的创建和生命周期管理方式。

3.1.4.1.分类

Spring 框架支持如下常见的作用域:

  1. Singleton:单例模式,一个 Bean 实例在整个应用中只创建一次,所有的请求都共享同一 Bean 实例。这是默认的作用域。

    ​ 当SpringIoC容器创建时, 就创建了Bean的实例

  2. Prototype:原型模式,每次请求都会创建一个新的 Bean 实例。即每个 Bean 引用都会创建一个新的实例。

  3. Request:每个 HTTP 请求(即每次 HTTP 请求)都会创建一个新的 Bean 实例,适用于 Web 应用开发。

  4. Session:每个用户会话(即用户登陆时创建的会话)都会创建一个新的 Bean 实例。

  5. GlobalSession:实例具有全局作用域,适用于 Portlet 应用开发,使用时需要在 Web.xml 中打开 Portlet 的支持。

    ​ 在新的版本中基本不再支持

  6. Application : bean被定义为在ServletContext的生命周期中复用一个单例对象。

  7. websocket:bean被定义为在websocket的生命周期中复用一个单例对象。

其中 单例模式与原型模式是在普通项目环境下就可以使用

但在Web环境下增加下面的监听器, 开启其它的作用域

<listener>
      <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>

3.1.4.2.单例模式

在 Spring 中,可以在 Bean 的定义中使用 scope 属性来指定作用域。

默认是Singleton单例模式.

启动测试代码:

		// 得到 SpringIoC 容器
		AbstractApplicationContext beanFactory = new ClassPathXmlApplicationContext("spring-config.xml");
		// 得到 id 是 hw 的第一个实例
		HouWang swk = (HouWang) beanFactory.getBean("hw");
		// 得到 id 是 hw 的第二个实例
		HouWang sds = (HouWang) beanFactory.getBean("hw");
		// 通过 == 判断 两个 实例的引用是否为同一个
		System.out.println(swk==sds);
		// 关闭容器
		beanFactory.close();
		// 再次 获取实例
		HouWang dzsf = (HouWang) beanFactory.getBean("hw");
		System.out.println("dzsf = " + dzsf);

得到结果

石破天惊
true
Exception in thread "main" java.lang.IllegalStateException: BeanFactory not initialized or already closed - call 'refresh' before accessing beans via the ApplicationContext

只打印了一次 “石破天惊” 说明 构造方法只被调用一次, 也就是只实例化一次

打印 true 表明, 两个引用是同一个实例

后面的报错说明 , 当关闭SpringIoC容器后, 就不能再得到实例了, 也就是Bean的实例只在SpringIoC容器的生命周期之内

3.1.4.3.原型模式

修改Spring的配置文件, 通过 scope属性 调整 hw的作用域为 prototype 原型模式

 <bean id="hw" class="com.yuan.spring.beans.HouWang" scope="prototype"   ></bean>

再次测试上面的代码 , 得到的结果

石破天惊
石破天惊
false

打印了两次 “石破天惊” , 说明 实例化两次, 说明在每一次getBean()时都实例化新的对象

所以通过 “==” 判断返回 false

3.1.5.依赖注入

Spring 依赖注入(Dependency Injection)是 Spring 框架的核心特性之一。它允许我们从外部配置文件或注解中将对象的依赖关系注入到对象中,以达到松散耦合和易于维护的目的。

所谓依赖注入, 本质来是为应用对象的私有属性赋值

Spring 依赖注入主要有以下几种类型:

  1. 构造函数注入(Constructor injection):通过构造函数将依赖项传递给 Spring 容器创建的对象,通常适用于必须注入的依赖项。

  2. Setter 方法注入(Setter injection):通过 set 方法将依赖项传递给对象,通常适用于可选依赖项。

  3. 字段注入(Field injection):通过对象的字段(即属性)将依赖项注入到对象中。通常在属性上使用注解

  4. 接口注入(Interface injection):通过实现接口向对象注入依赖项,通常使用 ApplicationContextAware 接口实现。

以上注入方式的选择取决于应用程序的需求和使用环境。例如,如果我们需要在对象创建时立即注入一些必需依赖项,则最好使用构造函数注入;如果我们需要在运行时注入可选依赖项,则最好使用 Setter 方法注入。

3.1.5.1.构造函数注入

修改配置文件, 利用有参构造器为mingZi属性赋值

<constructor-arg> : 配置有参构造注入

index : 参数的序号

value : 为参数赋的值

    <bean id="hw" class="com.yuan.spring.beans.HouWang" >
        <constructor-arg index="0" value="齐天大圣"></constructor-arg>
    </bean>

测试, 调用 打招呼方法

		// 得到 SpringIoC 容器
		AbstractApplicationContext beanFactory = new ClassPathXmlApplicationContext("spring-config.xml");
		// 得到 id 是 hw 的第一个实例
		HouWang swk = (HouWang) beanFactory.getBean("hw");
		// 调用打招呼方法
		swk.daZhaoHu();

得到结果可以看到, 调用了有参构造器, 并为 mingZi 赋值

我齐天大圣来了
大家好,我是齐天大圣

3.1.5.2.Setter 方法注入

再次修改 配置文件

<property> : 配置Setter 方法注入

name : 与 Setter方法名配置 , 如 : 类中有 setMingZi(String mingZi) , setYg(IYaoGuai yg) 等方法

value : 赋简单值

ref : 赋 对象 值, 如 : nmw 对应 的 <bean id="nmw">

    <bean id="hw" class="com.yuan.spring.beans.HouWang"  >
        <property name="mingZi" value="齐天大圣"></property>
        <property name="yg" ref="nmw"></property>
    </bean>
    
    <bean id="hhr" class="com.yuan.spring.beans.HongHair"></bean>
    <bean id="tsgz" class="com.yuan.spring.beans.TieShanGongZhu"></bean>
    <bean id="nmw" class="com.yuan.spring.beans.NiuMoWang"></bean>

测试, 调用 打招呼, 打妖怪 方法

		// 得到 SpringIoC 容器
		AbstractApplicationContext beanFactory = new ClassPathXmlApplicationContext("spring-config.xml");
		// 得到 id 是 hw 的第一个实例
		HouWang swk = (HouWang) beanFactory.getBean("hw");
		// 调用打招呼方法
		swk.daZhaoHu();
		// 调用 打妖怪方法
		swk.daYaoGuai();

得到结果可以看到, 打妖怪 依赖的是 NiuMoWang 牛魔王 类 , 可以修改配置文件 再测试

石破天惊
大家好,我是齐天大圣
啊!我牛魔王会回来的!
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。