【Spring笔记02】Spring中的IOC容器和DI依赖注入介绍

这篇文章,主要介绍一下Spring中的IOC容器和DI依赖注入两个概念。

目录

一、IOC控制反转

1.1、什么是IOC

1.2、两种IOC容器

(1)基于BeanFactory的IOC容器

(2)基于ApplicationContext的IOC容器

二、DI依赖注入

2.1、什么是DI

2.2、四种依赖注入方式

(1)setter方法注入

(2)构造方法注入

(3)工厂方法注入

(4)静态方法注入


一、IOC控制反转

1.1、什么是IOC

IOC,英文全称是:Inversion Of Control,中文含义叫做:控制反转。

那具体什么是控制反转呢???

所谓的控制反转,是指:以前我们创建对象的方式是程序开发人员显式的通过【new】关键字进行创建,而到了Spring框架里面,我们对象的创建全部交给了Spring去创建,程序开发人员不需要知道对象是如何创建的,开发人员只需要从Spring里面获取需要的对象实例就可以使用了,这个过程我们就叫做控制反转。

控制反转,是一种主从换位的思想,就是说以前是开发人员创建对象,现在是Spring框架替我们创建对象,这就是将主从关系颠倒过来了。

控制反转的好处是什么呢???

我们可以看到,使用控制反转,可以不用显式的通过【new】创建对象,这样就可以减少很多的代码编写,提高一下开发效率了呗。

1.2、两种IOC容器

IOC容器主要作用就是:统一管理Bean的生命周期,以及Bean和Bean之间的依赖关系。

Spring框架里面,给我们提供了两种IOC容器,分别是:【BeanFactory】和【ApplicationContext】两大类。

(1)基于BeanFactory的IOC容器

BeanFactory位于spring-beans的jar包里面,是一个接口,它是Spring提供的最简单的IOC容器,基于BeanFactory接口实现的IOC容器只具备IOC和DI的功能,也就是说,BeanFactory的IOC容器只能够管理Bean的生命周期,以及Bean之间的依赖关系。

BeanFactory接口常见的实现类是:【XmlBeanFactory】类,这是一个通过读取XML配置文件的IOC容器。

BeanFactory特点:

功能简单,只具备IOC和DI的实现。

Bean实例化采用懒加载的方式(懒加载:只能主动调用getBean()方法获取Bean实例的时候才会去new创建对象)。

BeanFactory接口常用方法:

getBean():获取一个Bean对象。

BeanFactory常见实现类:

XmlBeanFactory类,这个类目前已经废弃,不推荐使用了。

BeanFactory代码案例:

public class ApplicationTest {public static void main(String[] args) throws FileNotFoundException {beanFactory();}private static void beanFactory() throws FileNotFoundException {// 1、获取 BeanFactory 容器ClassPathResource resource = new ClassPathResource("spring.xml");BeanFactory beanFactory = new XmlBeanFactory(resource);// 2、获取 bean 对象User user = beanFactory.getBean("user", User.class);}
}

(2)基于ApplicationContext的IOC容器

ApplicationContext是BeanFactory的一个子接口,基于ApplicationContext实现的IOC容器不仅具备BeanFactory的所有功能,并且还提供了额外的一些功能,例如:事件监听、国际化等等企业级功能。

ApplicationContext特点:

容器启动时候,就会实例化所有配置的Bean对象。

提供更多的功能,例如:事件传播,国际化等等功能。

ApplicationContext常见实现类:

ClassPathXmlApplicatinContext实现类:加载类路径下的配置文件(即:加载【src/main/resources】目录下路径)。

FileSystemXmlApplicationContext实现类:加载系统路径下中的配置文件(这个必须写完整的XML文件路径)。

ApplicationContext案例代码:

public class ApplicationTest {public static void main(String[] args) {applicationContext();}private static void applicationContext() {// 1、获取 ApplicationContext 容器ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");// 2、获取 Bean 对象User user = context.getBean("user", User.class);}
}

IOC是一种程序设计思想,并不是一种技术,而要实现IOC则需要通过DI依赖注入的方式,下面介绍一下什么是DI依赖注入???

二、DI依赖注入

2.1、什么是DI

DI,英文全称是:Dependency Injection,中文含义叫做:依赖注入。

依赖注入:这里的依赖是指Bean之间的依赖关系(引用关系,例如:A类使用B类对象,C类使用A类对象),注入是指给某个类中的属性赋值,依赖注入可以理解为当某个A类中引用了B类的实例对象,Spring会动态的将B类对象赋值到A类的属性里面,Spring框架这个动态赋值的操作我们就称为依赖注入。

在Spring框架里面,如果我们需要使用某个Bean对象的时候,我们不用自己创建就可以直接使用这个Bean对象,这是因为Spring框架已经给我们注入了所有的Bean。

什么是意思呢,举个栗子看看:

如果我们在某个A类里面使用到了B类的一个实例,此时Spring会自动将B类的实例注入到当前A类里面,而不需要我们再次通过new创建B的对象实例。

简单理解,依赖注入就是Spring框架自动帮我们把某个类中的属性已经赋值了,所以我们在使用的时候,就可以不用再次赋值,也就不会出现空指针的情况啦。

依赖注入的好处:通过依赖注入,可以极大程度上面降低类之间的耦合度,实现类与类之间的松耦合。

2.2、四种依赖注入方式

Spring框架中提供了四种依赖注入的方式,分别是如下所示:

  • 通过setter方法实现依赖注入
  • 通过工厂方法实现依赖注入
  • 通过静态工厂方法实现依赖注入
  • 通过构造方法实现依赖注入

(1)setter方法注入

Spring框架可以通过调用属性的【setter】方法进行属性赋值,从而实现依赖注入。Spring通过反射机制调用属性的【setXXX()】方法,将所需要的对象赋值给对应的类属性(注意:和具体的属性名称没有关系,只不过我们习惯将属性名称和setter方法名称命名相同)。

创建【Setter】测试类

public class Setter {private String uid;private String name;private String pass;public String getUid() {return uid;}public void setUid(String uid) {this.uid = uid;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getPassword() {return pass;}// 注意:这里的 setPassword 方法名称和 Pass属性不同public void setPassword(String pass) {this.pass = pass;}
}

配置spring.xml文件

setter方法注入,对应XML配置中的【<property>】标签。我们通过【<property>】标签就是采用的setter方法进行属性注入。

<?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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 配置 Setter类 --><bean id="setter" class="com.spring.demo.pojo.Setter"><!-- 属性赋值 --><property name="uid" value="1001"/><property name="name" value="朱友斌"/><!-- 属性名称要和 setXxx() 对应的名称相同 --><property name="password" value="123456"/></bean></beans>

测试setter方法注入

public class SetterTest {public static void main(String[] args) {// 1、获取 ApplicationContext 容器ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");// 2、获取 Bean 对象Setter setter = context.getBean("setter", Setter.class);System.out.println(setter.getUid());System.out.println(setter.getName());System.out.println(setter.getPassword());}
}

以上,就是通过setter方法进行属性注入的一个案例,下一篇文章会详细的介绍各种依赖注入的方式以及各种数据类型的依赖注入,这里先大致有个了解。

(2)构造方法注入

Spring也支持通过构造方法进行属性注入(属性赋值),主要是调用Bean相应的构造方法。

Spring里面通过在XML配置文件中使用【<constructor-arg>】标签,就可以实现构造方法注入属性。

创建【Constructor】测试类

public class Constructor {public String uid;public String name;public String pass;// 构造方法注入属性public Constructor(String uid, String name, String pass) {this.uid = uid;this.name = name;this.pass = pass;}
}

添加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"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 配置 Constructor 类 --><bean id="constructor" class="com.spring.demo.pojo.Constructor"><!-- 构造方法属性赋值 --><constructor-arg name="uid" value="1001"/><constructor-arg name="name" value="朱友斌"/><constructor-arg name="pass" value="123456"/></bean></beans>

测试构造方法注入

public class ConstructorTest {public static void main(String[] args) {// 1、获取 ApplicationContext 容器ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");// 2、获取 Bean 对象Constructor constructor = context.getBean("constructor", Constructor.class);System.out.println(constructor.uid);System.out.println(constructor.name);System.out.println(constructor.pass);}
}


构造方法注入,有两种方式,分别是:

  • 第一种方式:指定具体的参数名称进行赋值。
  • 第二种方式:根据构造方法中的参数位置进行赋值。

上面我们就是通过【<constructor-arg>】标签的参数名称进行赋值,这里我再给出通过参数位置(参数位置从0开始编号)进行赋值的代码配置,如下所示:

<bean id="constructor" class="com.spring.demo.pojo.Constructor"><!-- 构造方法属性赋值 --><constructor-arg index="0" value="1001"/><constructor-arg index="1" value="朱友斌"/><constructor-arg index="2" value="123456"/>
</bean>

(3)工厂方法注入

Spring框架实例化Bean是调用无参构造方法实现的,所以如果某个Bean没有无参构造方法,并且没有通过有参构造方法进行注入,那么在Spring实例化的时候就会失败,并且抛出异常。如何解决这个Bean无法实例化的问题呢???

Spring框架提供了实例工厂方法,我们可以通过工厂方法进行实例化操作。

如何使用实例工厂方法进行依赖注入???

  • 使用实例工厂方法,需要创建一个实例工厂,然后在工厂类中提供一个创建实例的方法。
  • 然后在目标Bean里面,配置【factory-bean】和【factory-method】两个属性。
  • 【factory-bean】作用:告诉Spring,当前这个Bean是从哪个实例工厂bean获取。
  • 【factory-method】作用:告诉Spring,当前这个Bean是从工厂类中哪个method方法进行获取。

创建【Person】实体类

public class Person {public Integer pid;public String name;// 无参构造方法public Person(Integer pid, String name) {this.pid = pid;this.name = name;}
}

创建【FactoryMethod】工厂类

public class FactoryMethod {// 工厂方法public Person getInstance() {return new Person(1002, "朱友斌");}
}

添加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"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 配置工厂类 --><bean id="factory" class="com.spring.demo.pojo.FactoryMethod"/><!-- 配置 Person 类 --><bean id="person" class="com.spring.demo.pojo.Person" factory-bean="factory" factory-method="getInstance"/></beans>

在XML配置文件里面,需要配置【factory-bean】和【factory-method】两个属性,这是告诉Spring,当前这个Person类实例化,是去找一个叫做【factory】的bean里面的【getInstance()】方法进行获取。


编写测试类,查看Person是否实例化成功

public class FactoryMethodTest {public static void main(String[] args) {// 1、获取 ApplicationContext 容器ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring02.xml");// 2、获取 Bean 对象Person person = context.getBean("person", Person.class);System.out.println(person.pid);System.out.println(person.name);}
}

以上,就是通过实例工厂方法进行Bean的依赖注入。

(4)静态方法注入

从(3)里面,我们学习了通过实例工厂方法进行Bean的依赖注入,基本分为两个步骤,第一步是创建工程类的Bean,第二步是根据工程类的Bean创建目标Bean的实例。

这里我们可以发现,我们创建目标Bean的时候依赖于工厂类的Bean对象,所以这里有个问题,如果我们的工厂类的Bean也没有办法实例化,那实例工厂方法注入不就没有办法实现了吗???

为了解决实例工厂方法的缺陷,Spring也提供了静态工厂方法进行Bean的注入。既然实例工厂没办法实例化,那我们就采用静态工厂,因为静态工厂是可以直接通过类进行访问的,和实例对象没有关系,所以我们就可以通过一个静态方法,这个静态方法就是用于创建目标Bean的实例对象。

静态工厂方法依赖注入

  • 创建静态工厂类,提供一个静态工厂方法,用于获取目标Bean的对象。
  • 然后在配置文件里面通过【factory-method】属性配置获取bean对象的静态方法。

创建【StaticFactoryMethod】静态工厂类

public class StaticFactoryMethod {// 静态工厂方法public static Person getInstance() {return new Person(1002, "朱友斌");}
}

添加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"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 通过静态工厂方法获取 Person 类实例 --><bean id="person" class="com.spring.demo.pojo.StaticFactoryMethod"  factory-method="getInstance"/></beans>

创建测试类,测试是否依赖注入成功

public class StaticFactoryMethodTest {public static void main(String[] args) {// 1、获取 ApplicationContext 容器ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring03.xml");// 2、获取 Bean 对象Person person = context.getBean("person", Person.class);System.out.println(person.pid);System.out.println(person.name);}
}

以上,就是通过静态工厂方法进行依赖注入。

综上,讲述了Spring框架中的IOC容器,DI依赖注入以及四种依赖注入的方式。依赖注入的四种方式主要记住setter方法和构造方法注入,因为实例工厂方法、静态工厂方法在实际开发中不常用

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/126052.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Python】读取显示pgm图像文件

文章目录 零. 前言一. pgm基本概念二. pgm基本信息读取三. pgm图像渲染四. 代码优化 零. 前言 这学期要学多媒体信息隐藏对抗&#xff0c;发现其中的图像数据集文件都是pgm文件形式的。虽然是图像文件&#xff0c;但是却不能直接通过图像查看器来打开&#xff0c;上网一搜&…

大模型 Decoder 的生成策略

本文将介绍以下内容&#xff1a; IntroductionGreedy Searchbeam searchSamplingTop-K SamplingTop-p (nucleus) sampling总结 一、Introduction 1、简介 近年来&#xff0c;由于在数百万个网页数据上训练的大型基于 Transformer 的语言模型的兴起&#xff0c;开放式语言生…

怎么利用互联网赚钱,网上赚钱的7种方法

互联网的兴起改变了我们的生活方式&#xff0c;不仅让我们的世界更为便捷&#xff0c;也为我们提供了赚钱的机会。越来越多的人开始通过互联网实现财富梦想。你是否曾想过&#xff0c;如何利用互联网来赚钱呢&#xff1f;今天&#xff0c;我将为大家分享七种赚钱方法&#xff0…

Leetcode hot 100之双指针(快慢指针、滑动窗口)

目录 数组 有序的平方仍有序 删除/覆盖元素 移动零&#xff1a;交换slow和fast 滑动窗口&#xff1a;最短的连续子串&#xff08;r可行解->l--最短解&#xff09; 最小长度的子数组 求和&#xff1a;sort、l i 1, r len - 1 三数之和abctarget 四数之和abcdtarg…

汽车类、TPS7B8225QDGNRQ1、TPS7B8233EPWPRQ1、TPS7B8601QKVURQ1 40V、低压降 (LDO) 线性稳压器

一、TPS7B82-Q1 汽车类 300mA、高压、超低 IQ 低压降稳压器 &#xff08;介绍&#xff09;在汽车电池连接应用中&#xff0c;低静态电流 (IQ) 对于省电和延长电池寿命而言至关重要。对于始终开启的系统&#xff0c;必须要实现超低 IQ。 TPS7B82-Q1 是一款旨在在 3V 至 40V&…

【C++】运算符重载 ⑧ ( 左移运算符重载 | 友元函数 / 成员函数 实现运算符重载 | 类对象 使用 左移运算符 )

文章目录 一、左移运算符重载1、友元函数 / 成员函数 实现运算符重载2、类对象 使用 左移运算符3、左移运算符 << 重载 二、完整代码示例 一、左移运算符重载 1、友元函数 / 成员函数 实现运算符重载 运算符重载 的正规写法一般都是 使用 成员函数 的形式 实现的 ; 加法…

Llama2-Chinese项目:8-TRL资料整理

TRL&#xff08;Transformer Reinforcement Learning&#xff09;是一个使用强化学习来训练Transformer语言模型和Stable Diffusion模型的Python类库工具集&#xff0c;听上去很抽象&#xff0c;但如果说主要是做SFT&#xff08;Supervised Fine-tuning&#xff09;、RM&#x…

Python脚本实现xss攻击

实验环境&#xff1a;zd靶场、vscode 知识点 requests.session() 首先我们需要先利用python requests模块进行登录&#xff0c;然后利用开启session记录&#xff0c;保持之后的操作处于同一会话当中 requests.session()用于创建一个会话(session)的实例对象。使用requests库…

【JavaEE】多线程进阶(一)饿汉模式和懒汉模式

多线程进阶&#xff08;一&#xff09; 文章目录 多线程进阶&#xff08;一&#xff09;单例模式饿汉模式懒汉模式 本篇主要引入多线程进阶的单例模式&#xff0c;为后面的大冰山做铺垫 代码案例介绍 单例模式 非常经典的设计模式 啥是设计模式 设计模式好比象棋中的 “棋谱”…

Python无废话-办公自动化Excel格式美化

设置字体 在使用openpyxl 处理excel 设置格式&#xff0c;需要导入Font类&#xff0c;设置Font初始化参数&#xff0c;常见参数如下&#xff1a; 关键字参数 数据类型 描述 name 字符串 字体名称&#xff0c;如Calibri或Times New Roman size 整型 大小点数 bold …

做外贸独立站选Shopify还是WordPress?

现在确实会有很多新人想做独立站&#xff0c;毕竟跨境电商平台内卷严重&#xff0c;平台规则限制不断升级&#xff0c;脱离平台“绑架”布局独立站&#xff0c;才能获得更多流量、订单、塑造品牌价值。然而&#xff0c;在选择建立外贸独立站的过程中&#xff0c;选择适合的建站…

TinyWebServer整体流程

从main主函数开始&#xff1a; 一、定义MySQL数据库的账号、密码和用到的数据库名称。 二、调用Config获得服务器初始化属性 在这一步确定触发模式端口等信息。 三、创建服务器实例对象 设置根目录、开辟存放http连接对象的空间&#xff0c;开辟定时器空间。 四、利用Confi…