Spring中IOC思想(2)和依赖注入详解

本文深入探讨了Spring框架中的IOC思想,包括控制反转和依赖注入的概念。通过具体案例,详细解释了如何使用XML配置文件在Spring容器中实例化类,以及如何通过setter方法和构造方法进行依赖注入。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在上次更新完《Spring中IOC思想(1)》博客后,也有段时间了,结合我对IOC更深层次的理解,我再写一篇关于IOC的博客

IOC

Spring框架的一个特点之一就是IOC思想

IOC思想其实就是将创建对象的权利进行转变,也就是控制反转,另外一个名称是依赖注入

在我们之前的博客讲解中,我们讲解到了个别案例,使用的是三层dao–>service–>前端

service层中我们需要对dao层的中的类进行实例化,只有这样,我们才能在service层中通过调用dao层中的类的方法来对数据库进行增删改查、获得我们想要的数据。这也就需要我们在一个类中对另外一个类进行实例化,这样程序员在无意中就增加了程序的耦合性,而Java编程的思想其实是高内聚低耦合,对项目的后期升级维护不利,那么有没有改进的方法?

这就需要说到Spring的作用

我在IDE中新建一个普通Maven项目,用于IOC的讲解

实体类的编写

在这里插入图片描述
这是新建的项目自动生成的目录,在java目录下创建com目录,在com目录下创建westos目录,在westos目录下创建pojo类,在pojo类中进行实体类的编写

在pojo中创建实体类HelloSpring

package com.westos.pojo;

public class HelloSpring {
    
    private String username;

    public void setUsername(String username) {
        this.username = username;
    }
    
    public void show(){
        System.out.println(username + ",你好,欢迎使用Spring");
    }
}

在创建好这个实体类后,和之前的将类使用关键字new进行实例化不同,我们使用Spring自带的方法来进行

因为我们需要使用Spring,所以我们需要导入Spring的一些依赖

依赖的导入

首先,为了防止资源在导入和导出时候发生问题,我们需要在pom.xml文件中新建<build>标签,在该标签中写入

<!--解决资源导出问题-->
<resources>
  <resource>
    <directory>src/main/java</directory>
    <includes>
      <include>**/*.properties</include>
      <include>**/*.xml</include>
    </includes>
    <filtering>false</filtering>
  </resource>
  <resource>
    <directory>src/main/resources</directory>
    <includes>
      <include>**/*.properties</include>
      <include>**/*.xml</include>
    </includes>
    <filtering>false</filtering>
  </resource>
</resources>

之后我们在导入Spring需要的依赖

<!--junit包单元测试-->
<dependency>
  <groupId>junit</groupId>
  <artifactId>junit</artifactId>
  <version>4.11</version>
  <scope>test</scope>
</dependency>

<!-- Spring MVC 及 Spring系列包 -->
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring-webmvc</artifactId>
  <version>4.3.24.RELEASE</version>
</dependency>

因为我们现在创建的项目是个比较简单的项目,没有用到前端和web,主要用来对IOC思想进行讲解,所以只导入上面的两个依赖
在这里插入图片描述查看项目结构,可以看到导包成功

applicationContext.xml文件的编写

在resources目录下创建applicationContext.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/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="..." class="...">
        <!-- collaborators and configuration for this bean go here -->
    </bean>

    <bean id="..." class="...">
        <!-- collaborators and configuration for this bean go here -->
    </bean>

    <!-- more bean definitions go here -->

</beans>

这是我们在官网上面找到的,官网上面直接给好了<bean>标签的使用格式,删除多余部分,开始文件的编写
在这里插入图片描述完整的文件如下

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--将HelloSpring类进行实例化-->
    <bean id="hellospring" class="com.westos.pojo.HelloSpring">
        <!--对实例化的对象中的成员变量进行赋值-->
        <property name="username" value="强静州"></property>
    </bean>

</beans>

在Spring中我们使用xml配置文件来对类进行实例化

Spring的另外一个特点就是容器,在这个容器中可以创建对象、建立对象之间的依赖关系以及管理对象的生命周期

也就是说,我们将类交给Spring容器进行保管,在Spring容器中对类进行实例化,这样我们在需要一个类的对象时不需要自己使用代码来进行创建,直接从容器中取出来就行

在使用Spring框架后,类的实例不再由调用者创建,而是由Spring容器来进行创建,Spring容器会负责控制程序之间的关系,而不是由调用者的程序代码直接控制,这样降低了对象之间的耦合性,与此同时,对象的创建 控制权由应用程序代码交给了Spring容器,控制权发生了反转,这就是我们上面讲解到控制反转

测试

我们在test目录下创建测试类
在这里插入图片描述
对我们之前的代码进行测试,我们先初始化Spring容器,并加载applicationContext.xml文件;之后从容器中取出已经实例化的对象,调用对象的成员方法

代码实现:

package com.westos;

import com.westos.pojo.HelloSpring;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
    @org.junit.Test
    public void HelloSppring(){
        //初始化Spring容器并且并加载applicationContext.xml文件
        ApplicationContext apc = new ClassPathXmlApplicationContext("applicationContext.xml");

        //通过Spring容器获取HelloSpring类的实例hellospring
        HelloSpring hellospring = (HelloSpring)apc.getBean("hellospring");

        //调用该实例的成员方法
        hellospring.show();
    }
}

运行结果
在这里插入图片描述运行成功

依赖注入概念

通过上面的例子主要是想讲解控制反转的概念,上面又提到IOC的另外一个名称是依赖注入,为什么呢?

这其实是一个东西从不同的概念来看待,从程序员角度来看的话,IOC是控制反转;但是从Spring角度来看的话,其实是依赖注入

在编写applicationContext.xml文件时为了能让Spring容器将我们需要使用的实体类进行实例化,存在下面的代码

    <!--将HelloSpring类进行实例化-->
    <bean id="hellospring" class="com.westos.pojo.HelloSpring">
        <!--对实例化的对象中的成员变量进行赋值-->
        <property name="username" value="强静州"></property>
    </bean>
  1. <bean>标签的作用是将指定类配置给Spring,让Spring创建该类的实例
  2. <property>标签的作用是为实例中的属性赋值

通过上面的两个标签的结合使用,可以将类进行实例化并且将类中的成员变量赋值,而给成员变量进行赋值的这个过程其实就可以看做是依赖注入,因为成员变量如果是个其他类的实例的话,我们相当于将这个类的实例所以依赖的其他类进行了注入入,这就是依赖注入

IOC从不同的角度来看的话就有两种结果:控制反转依赖注入

依赖注入详解

依赖注入又分为两种setter方法注入构造方法注入

setter方法注入

在我们之前的applicationContext.xml文件中使用的依赖注入方式为setter方法注入

这个方法其实是调用实体类的无参构造将实体类进行实例化,之后根据这个实例的反射来调用相关成员变量的set方法进行依赖的注入,所以在我们编写的实体类中有username的set方法,而且必须要有无参构造

package com.westos.pojo;

public class HelloSpring {
    
    private String username;

    public void setUsername(String username) {
        this.username = username;
    }
    
    public void show(){
        System.out.println(username + ",你好,欢迎使用Spring");
    }
}

setter方法注入的基本格式为

 <property name="username" value="强静州"></property>

我们使用到了<property>标签,在次之前我们先讲解一下<bean>标签的作用,之前讲解过,它的作用是将类进行实例化

<bean>标签的主要属性为:

  1. id属性用来标识实例名,也就是类的对象名
  2. calss属性指定待实例化的类的全路径名

<property>标签的主要属性为:

  1. name属性用来指定实体类的实例中的待赋值属性,在我上面举的例子中,name指定hellospring对象的username属性
  2. value属性就是给username属性赋的值

setter注入随着实例的属性的类型不同,也有多种注入方式:

常量注入
<!--普通字段-->
<property name="name" value="小明"/>
Bean注入
<!--引用其他bean使用ref-->
<!--上面一行的注释中的bean是什么意思呢?在Spring中将被Spring容器托管的类称为bean-->

<property name="address" ref="addr"/>
<!--addr是个实例名-->
数组注入
<!--数组的注入-->
<property name="books">
    <array>
        <value>西游记</value>
        <value>水浒传</value>
        <value>红楼梦</value>
        <value>三国演义</value>
    </array>
</property>
List注入
<!--List注入-->
<property name="hobbys">
    <list>
        <value>女孩</value>
        <value>代码</value>
        <value>电影</value>
        <value>音乐</value>
    </list>
</property>
Map注入

标签:<entry>

键:使用key

值: 使用value

<!--Map的注入-->
<property name="card">
    <map>
        <entry key="IdCard" value="666666888888884444"/>
        <entry key="银行卡" value="111122223333444"/>
    </map>
</property>
Set注入
<!--Set注入-->
<property name="games">
    <set>
        <value>王者荣耀</value>
        <value>贪玩蓝月</value>
        <value>绝地求生</value>
        <value>LOL</value>
    </set>
</property>
空值注入
<!--Null空值注入-->
<property name="girlFriend">
    <null/>
</property>
Properties注入

<props>标签

键使用key

值,在标签中间;

<!--Properties注入-->
<property name="info">
    <props>
        <prop key="学号">201932301</prop>
        <prop key="性别">男</prop>
        <prop key="姓名">小明</prop>
    </props>
</property>

在使用常规setter方法注入时,如果实例有多个属性也就是成员变量,我们要对属性一一赋值就非常麻烦

p空间注入方法

这里讲到一种注入方法是p空间注入方法

我们在applicationContext.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"
       
       <!--添加p命名空间的声明-->
       xmlns:p="http://www.springframework.org/schema/p"
       
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--将HelloSpring类进行实例化-->
    <bean id="hellospring" class="com.westos.pojo.HelloSpring">
        <!--对实例化的对象中的成员变量进行赋值-->
        <property name="username" value="强静州"></property>
    </bean>

</beans>

在添加完成后,我们就能在<bean>标签中直接使用p属性来对实例的属性进行注入

我们先对pojo目录中的实体类进行修改

package com.westos.pojo;

public class HelloSpring {

    private String username;
    private String sex;

    public void setUsername(String username) {
        this.username = username;
    }

    public void setSex(String sex) {
        this.sex = sex;
    }

    public void show(){
        System.out.println(username + ",你好,欢迎使用Spring");
        System.out.println(username + ",你好,你的性别是" + sex);
    }
}

修改完成后我们重写一遍applicationContext.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:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--将HelloSpring类进行实例化-->
    <bean id="hellospring" class="com.westos.pojo.HelloSpring">
        <!--对实例化的对象中的成员变量进行赋值-->
        <property name="username" value="强静州"></property>
        <property name="sex" value="男"></property>
    </bean>

    <bean id="hellospring1" class="com.westos.pojo.HelloSpring" p:username="强东刘" p:sex="男"/>

</beans>

我们新创建了一个对象叫hellospring1

之后进行测试

package com.westos;

import com.westos.pojo.HelloSpring;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
    @org.junit.Test
    public void HelloSppring(){
        //初始化Spring容器并且并加载applicationContext.xml文件
        ApplicationContext apc = new ClassPathXmlApplicationContext("applicationContext.xml");

        //通过Spring容器获取HelloSpring类的实例hellospring
        HelloSpring hellospring = (HelloSpring)apc.getBean("hellospring");
        HelloSpring hellospring1 = (HelloSpring)apc.getBean("hellospring1");

        //调用该实例的成员方法
        hellospring.show();
        hellospring1.show();
    }
}

运行结果
在这里插入图片描述
运行成功,从中也可以看出使用p空间注入的优点:当有实例有多个属性时,比<property>标签更加方便快捷

构造方法注入

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值