2025/2/25 -26《尚硅谷》——Spring依赖注入实例讲解(setter、构造器、特殊值处理、为类类型、数组类型、list集合类型、map集合类型的属性赋值、p命名空间等

目录

一、依赖注入之 Setter 注入

1. spring-ioc.xml 配置

2. 测试代码

3. 输出结果

4. 解析

二、依赖注入之构造器注入

演示一

1. spring-ioc.xml 配置

2. 测试代码

3. 输出结果

4. 解析

演示二

1. spring-ioc.xml 配置

2. Student.java代码

3. 测试代码

4. 输出结果

5.解析

三、依赖注入之特殊值处理

1. 空值处理

测试一:直接使用 value="null"

spring-ioc.xml 配置

测试二:使用   标签

spring-ioc.xml 配置

2. 特殊字符处理

解决方案一:使用 XML 实体

spring-ioc.xml 配置

解决方案二:使用 CDATA 节

spring-ioc.xml 配置

四、依赖注入之为类类型的属性赋值(引用外部的 Bean)

1. Student 类代码、 Clazz 类代码、spring-ioc.xml 配置

2. 测试代码

3. 输出结果

4. 解析

五、依赖注入之为类类型的属性赋值(级联方式和内部 Bean)——(2025/2/25-19:21:20)肝不动了,剩下的明天(2024/2/26)再写

演示一:级联方式赋值(未初始化 clazz 属性)

演示二:级联方式赋值(初始化 clazz 属性)

演示三:内部 Bean 赋值

演示四:内部 Bean 无法直接获取

六、依赖注入之为数组类型的属性赋值

1. spring-ioc.xml 配置

2. Student 类

3. 测试代码

4. 输出结果

5. 分析

七、依赖注入之为 List 集合类型的属性赋值

演示一:直接使用   标签

1. spring-ioc.xml 配置

2. Clazz 类

3. 测试代码

4. 输出结果

5. 分析

演示二:使用   标签

1. spring-ioc.xml 配置

2. 测试代码

3. 输出结果

4. 分析

八、依赖注入之为 Map 集合类型的属性赋值

1. spring-ioc.xml 配置

2. Student 类

3. Teacher 类

4. 测试代码

5. 输出结果

6. 分析

九、依赖注入之 p 命名空间


一、依赖注入之 Setter 注入

Setter 注入是通过调用类的 Setter 方法为属性赋值。

1. spring-ioc.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 http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!-- 未设置属性的 Bean -->
    <bean id="studentOne" class="com.atguigu.spring.pojo.Student"></bean>

    <!-- 使用 Setter 注入设置属性 -->
    <bean id="studentTwo" class="com.atguigu.spring.pojo.Student">
        <property name="sid" value="1001"></property>
        <property name="sname" value="张三"></property>
        <property name="age" value="23"></property>
        <property name="gender" value="男"></property>
    </bean>

</beans>
2. 测试代码
@Test
public void testDI(){
    // 获取 IOC 容器
    ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-ioc.xml");
    // 获取 Bean
    Student student = ioc.getBean("studentTwo", Student.class);
    System.out.println(student);
}
3. 输出结果
Student{sid=1001, sname='张三', age=23, gender='男'}
4. 解析
  • <property>:通过 Setter 方法为属性赋值。

    • name:属性名(与 Setter 方法名对应,例如 name="sid" 对应 setSid 方法)。

    • value:为属性设置的值。


二、依赖注入之构造器注入

演示一

构造器注入是通过调用类的构造方法为属性赋值。

1. spring-ioc.xml 配置
    <bean id="studentThree" class="com.atguigu.spring.pojo.Student">
        <constructor-arg  value="1002"></constructor-arg>
        <constructor-arg  value="李四"></constructor-arg>
        <constructor-arg  value="24"></constructor-arg>
        <constructor-arg  value="女"></constructor-arg>
    </bean>
2. 测试代码
    @Test
    public void testDI(){
        //获取IOC容器
        ApplicationContext  ioc = new ClassPathXmlApplicationContext("spring-ioc.xml");
        //获取bean
        Student student = ioc.getBean("studentThree", Student.class);
        System.out.println(student);
    }
3. 输出结果
Student{sid=1002, sname='李四', age=24, gender='女'}

进程已结束,退出代码为 0
4. 解析
  • <constructor-arg>:通过构造方法为属性赋值。

    • name:构造方法参数名。

    • value:为参数设置的值。

演示二
1. spring-ioc.xml 配置
    <bean id="studentTwo" class="com.atguigu.spring.pojo.Student">
        <property name="sid" value="1001"></property>
        <property name="sname" value="张三"></property>
        <property name="age" value="23" ></property>
        <property name="gender" value="男"></property>
    </bean>

    <bean id="studentThree" class="com.atguigu.spring.pojo.Student">
        <constructor-arg  value="1002"></constructor-arg>
        <constructor-arg  value="李四"></constructor-arg>
        <constructor-arg  value="女"></constructor-arg>
        <constructor-arg  value="24" name="age"></constructor-arg>
    </bean>
2. Student.java代码
package com.atguigu.spring.pojo;

public class Student implements Person {

    private Integer sid;
    private String sname;
    private Integer age;
    public String gender;
    private Double score;

    // 构造方法 1
    public Student(Integer sid, String sname, String gender, Integer age) {
        this.sid = sid;
        this.sname = sname;
        this.gender = gender;
        this.age = age;
    }

    // 构造方法 2
    public Student(Integer sid, String sname, String gender, Double score) {
        this.sid = sid;
        this.sname = sname;
        this.gender = gender;
        this.score = score;
    }

    // 无参构造方法
    public Student() {
    }

    // Getter 和 Setter 方法
    public Integer getSid() {
        return sid;
    }

    public void setSid(Integer sid) {
        this.sid = sid;
    }

    public String getSname() {
        return sname;
    }

    public void setSname(String sname) {
        this.sname = sname;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public Double getScore() {
        return score;
    }

    public void setScore(Double score) {
        this.score = score;
    }

    @Override
    public String toString() {
        return "Student{" +
                "sid=" + sid +
                ", sname='" + sname + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                ", score=" + score +
                '}';
    }
}
3. 测试代码
    @Test
    public void testDI(){
        //获取IOC容器
        ApplicationContext  ioc = new ClassPathXmlApplicationContext("spring-ioc.xml");
        //获取bean
        Student student = ioc.getBean("studentThree", Student.class);
        System.out.println(student);
    }
4. 输出结果
Student{sid=1002, sname='李四', age=null, gender='女', score=24.0}

进程已结束,退出代码为 0
5.解析
  • 构造器注入的灵活性

    • 如果类中有多个构造方法,Spring 会根据 <constructor-arg> 的参数数量和类型自动匹配对应的构造方法。

    • 在 Student 类中,有两个构造方法:

      1. Student(Integer sid, String sname, String gender, Integer age)

      2. Student(Integer sid, String sname, String gender, Double score)

    • 在 spring-ioc.xml 中,studentThree 的配置匹配了第一个构造方法,因为 age 是 Integer 类型。

  • name 属性

    • 在 <constructor-arg> 中使用 name 属性可以明确指定参数名,避免参数顺序错误。

    • 例如:<constructor-arg value="24" name="age"></constructor-arg>


三、依赖注入之特殊值处理

1. 空值处理

在 Spring 中,可以通过以下两种方式为属性设置空值:

测试一:直接使用 value="null"
spring-ioc.xml 配置
<bean id="studentFour" class="com.atguigu.spring.pojo.Student">
    <property name="sid" value="1003"></property>
    <property name="sname" value="王五"></property>
    <property name="gender" value="null"></property>
</bean>

 测试代码

@Test
public void testDI(){
    // 获取 IOC 容器
    ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-ioc.xml");
    // 获取 Bean
    Student student = ioc.getBean("studentFour", Student.class);
    System.out.println(student);
}

 输出结果

Student{sid=1003, sname='王五', age=null, gender='null', score=null}

解析

  • value="null":将 gender 属性设置为字符串 "null",而不是真正的 null 值。

  • 因此,gender 的值是字符串 "null",而不是 Java 中的 null

  • 注意:这种方式并不是真正的空值处理,而是将字符串 "null" 赋值给属性。


测试二:使用 <null/> 标签
spring-ioc.xml 配置
<bean id="studentFour" class="com.atguigu.spring.pojo.Student">
    <property name="sid" value="1003"></property>
    <property name="sname" value="王五"></property>
    <property name="gender">
        <null/>
    </property>
</bean>

 测试代码

@Test
public void testDI(){
    // 获取 IOC 容器
    ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-ioc.xml");
    // 获取 Bean
    Student student = ioc.getBean("studentFour", Student.class);
    System.out.println(student);
}

 输出结果

Student{sid=1003, sname='王五', age=null, gender='null', score=null}

解析

  • <null/>:将 gender 属性设置为真正的 null 值。

  • 在输出结果中,gender 显示为 'null',这是因为 toString() 方法将 null 值转换为字符串 "null"

  • 注意:如果直接调用 gender 的方法(如 toString()),会抛出 NullPointerException


2. 特殊字符处理

在 XML 中,某些字符(如 <>& 等)具有特殊含义,不能直接使用。以下是两种处理特殊字符的方式:

解决方案一:使用 XML 实体

XML 提供了一些预定义的实体来表示特殊字符,例如:

  • &lt; 表示 <

  • &gt; 表示 >

  • &amp; 表示 &

spring-ioc.xml 配置
<bean id="studentFour" class="com.atguigu.spring.pojo.Student">
    <property name="sid" value="1003"></property>
    <property name="sname" value="&lt;王五&gt;"></property>
    <property name="gender">
        <null/>
    </property>
</bean>

 输出结果

Student{sid=1003, sname='<王五>', age=null, gender='null', score=null}

 解析

  • &lt; 和 &gt;:分别表示 < 和 >

  • Spring 会自动将 XML 实体转换为对应的字符。


解决方案二:使用 CDATA 节

CDATA 节用于表示纯文本数据,XML 解析器会忽略其中的特殊字符。

spring-ioc.xml 配置
<bean id="studentFive" class="com.atguigu.spring.pojo.Student">
    <property name="sid" value="1003"></property>
    <property name="sname">
        <value><![CDATA[《王五》]]></value>
    </property>
    <property name="gender">
        <null/>
    </property>
</bean>

 测试代码

@Test
public void testDI(){
    // 获取 IOC 容器
    ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-ioc.xml");
    // 获取 Bean
    Student student = ioc.getBean("studentFive", Student.class);
    System.out.println(student);
}

 输出结果

Student{sid=1003, sname='《王五》', age=null, gender='null', score=null}

 解析

  • <![CDATA[ ... ]]>:CDATA 节中的内容会被视为纯文本,不会被 XML 解析器解析。

  • 适合处理包含大量特殊字符的文本。

四、依赖注入之为类类型的属性赋值(引用外部的 Bean)

1. Student 类代码、 Clazz 类代码、spring-ioc.xml 配置

 Student 类代码

package com.atguigu.spring.pojo;

public class Student {
    private Integer sid;      // 学生 ID
    private String sname;     // 学生姓名
    private Integer age;      // 学生年龄
    private String gender;    // 学生性别
    private Double score;     // 学生成绩
    private Clazz clazz;      // 学生所属班级

    // 构造方法、Getter 和 Setter 方法
    // toString 方法
}

 Clazz 类

package com.atguigu.spring.pojo;

public class Clazz {
    private Integer cid;      // 班级 ID
    private String cname;     // 班级名称

    // 构造方法、Getter 和 Setter 方法
    // toString 方法
}

spring-ioc.xml 配置

解析

  • <property name="clazz" ref="clazzOne">

    • name="clazz":表示 Student 类中的 clazz 属性。

    • ref="clazzOne":引用 ID 为 clazzOne 的 Bean。

  • Clazz 类

    • Clazz 是一个独立的类,表示班级信息,包含 cid(班级 ID)和 cname(班级名称)属性。

<!-- 定义 Student Bean -->
<bean id="studentFive" class="com.atguigu.spring.pojo.Student">
    <property name="sid" value="1004"></property>
    <property name="sname" value="赵六"></property>
    <property name="age" value="26"></property>
    <property name="gender" value="男"></property>
    <!-- 引用外部的 Clazz Bean -->
    <property name="clazz" ref="clazzOne"></property>
</bean>

<!-- 定义 Clazz Bean -->
<bean id="clazzOne" class="com.atguigu.spring.pojo.Clazz">
    <property name="cid" value="1111"></property>
    <property name="cname" value="最强王者班"></property>
</bean>
2. 测试代码
    @Test
    public void testDI(){
        //获取IOC容器
        ApplicationContext  ioc = new ClassPathXmlApplicationContext("spring-ioc.xml");
        //获取bean
        Student student = ioc.getBean("studentFive", Student.class);
        System.out.println(student);
    }
3. 输出结果
Student{sid=1004, sname='赵六', age=26, gender='男', score=null, clazz=Clazz{cid=1111, cname='最强王者班'}}

进程已结束,退出代码为 0
4. 解析
  1. 类类型属性

    • Student 类中的 clazz 属性是 Clazz 类型的对象。

    • 通过 <property name="clazz" ref="clazzOne">,将 clazzOne Bean 注入到 Student 的 clazz 属性中。

  2. Bean 的引用

    • 使用 ref 属性引用外部 Bean。

    • ref="clazzOne" 表示引用 ID 为 clazzOne 的 Bean。

  3. 输出结果

    • Student 对象的 clazz 属性被成功注入,值为 Clazz{cid=1111, cname='最强王者班'}

五、依赖注入之为类类型的属性赋值(级联方式和内部 Bean)——(2025/2/25-19:21:20)肝不动了,剩下的明天(2024/2/26)再写

演示一:级联方式赋值(未初始化 clazz 属性)

spring-ioc.xml 配置

<bean id="studentFive" class="com.atguigu.spring.pojo.Student">
    <property name="sid" value="1004"></property>
    <property name="sname" value="赵六"></property>
    <property name="age" value="26"></property>
    <property name="gender" value="男"></property>
    <!-- 级联方式赋值 -->
    <property name="clazz.cid" value="2222"></property>
    <property name="clazz.cname" value="远大前程班"></property>
</bean>

<bean id="clazzOne" class="com.atguigu.spring.pojo.Clazz">
    <property name="cid" value="1111"></property>
    <property name="cname" value="最强王者班"></property>
</bean>

 测试代码

@Test
public void testDI(){
    // 获取 IOC 容器
    ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-ioc.xml");
    // 获取 Bean
    Student student = ioc.getBean("studentFive", Student.class);
    System.out.println(student);
}

 输出结果

二月 26, 2025 11:29:04 上午 org.springframework.context.support.AbstractApplicationContext refresh
警告: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'studentFive' defined in class path resource [spring-ioc.xml]: Error setting property values; nested exception is org.springframework.beans.NullValueInNestedPathException: Invalid property 'clazz' of bean class [com.atguigu.spring.pojo.Student]: Value of nested property 'clazz' is null

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'studentFive' defined in class path resource [spring-ioc.xml]: Error setting property values; nested exception is org.springframework.beans.NullValueInNestedPathException: Invalid property 'clazz' of bean class [com.atguigu.spring.pojo.Student]: Value of nested property 'clazz' is null

 分析

  • 问题原因

    • 在 Student 类中,clazz 属性未初始化(即 null)。

    • 尝试通过 clazz.cid 和 clazz.cname 为 clazz 的属性赋值时,由于 clazz 为 null,导致抛出 NullValueInNestedPathException 异常。

  • 解决方案

    • 需要先初始化 clazz 属性,例如通过引用外部 Bean 或内部 Bean。


演示二:级联方式赋值(初始化 clazz 属性)

spring-ioc.xml 配置

<bean id="studentFive" class="com.atguigu.spring.pojo.Student">
    <property name="sid" value="1004"></property>
    <property name="sname" value="赵六"></property>
    <property name="age" value="26"></property>
    <property name="gender" value="男"></property>
    <!-- 引用外部 Bean -->
    <property name="clazz" ref="clazzOne"></property>
    <!-- 级联方式赋值 -->
    <property name="clazz.cid" value="2222"></property>
    <property name="clazz.cname" value="远大前程班"></property>
</bean>

<bean id="clazzOne" class="com.atguigu.spring.pojo.Clazz">
    <property name="cid" value="1111"></property>
    <property name="cname" value="最强王者班"></property>
</bean>

测试代码

@Test
public void testDI(){
    // 获取 IOC 容器
    ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-ioc.xml");
    // 获取 Bean
    Student student = ioc.getBean("studentFive", Student.class);
    System.out.println(student);
}

 输出结果

Student{sid=1004, sname='赵六', age=26, gender='男', score=null, clazz=Clazz{cid=2222, cname='远大前程班'}}

 分析

  • 关键点

    • 通过 <property name="clazz" ref="clazzOne"> 初始化了 clazz 属性。

    • 然后通过 <property name="clazz.cid" value="2222"> 和 <property name="clazz.cname" value="远大前程班"> 修改了 clazz 的属性值。

  • 结果

    • clazz 的属性值被成功修改为 Clazz{cid=2222, cname='远大前程班'}


演示三:内部 Bean 赋值

spring-ioc.xml 配置

<bean id="studentFive" class="com.atguigu.spring.pojo.Student">
    <property name="sid" value="1004"></property>
    <property name="sname" value="赵六"></property>
    <property name="age" value="26"></property>
    <property name="gender" value="男"></property>
    <!-- 内部 Bean -->
    <property name="clazz">
        <bean class="com.atguigu.spring.pojo.Clazz">
            <property name="cid" value="2222"></property>
            <property name="cname" value="远大前程"></property>
        </bean>
    </property>
</bean>

测试代码

@Test
public void testDI(){
    // 获取 IOC 容器
    ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-ioc.xml");
    // 获取 Bean
    Student student = ioc.getBean("studentFive", Student.class);
    System.out.println(student);
}

 输出结果

Student{sid=1004, sname='赵六', age=26, gender='男', score=null, clazz=Clazz{cid=2222, cname='远大前程'}}

 分析

  • 关键点

    • 使用 <property name="clazz"> 定义了一个内部 Bean。

    • 内部 Bean 只能在当前 Bean 的内部使用,无法通过 IOC 容器直接获取。

  • 结果

    • clazz 属性被成功注入,值为 Clazz{cid=2222, cname='远大前程'}


演示四:内部 Bean 无法直接获取

spring-ioc.xml 配置

<bean id="studentFive" class="com.atguigu.spring.pojo.Student">
    <property name="sid" value="1004"></property>
    <property name="sname" value="赵六"></property>
    <property name="age" value="26"></property>
    <property name="gender" value="男"></property>
    <!-- 内部 Bean -->
    <property name="clazz">
        <bean id="clazzInner" class="com.atguigu.spring.pojo.Clazz">
            <property name="cid" value="2222"></property>
            <property name="cname" value="远大前程"></property>
        </bean>
    </property>
</bean>

测试代码

@Test
public void testDI() {
    // 获取 IOC 容器
    ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-ioc.xml");
    // 尝试获取内部 Bean
    Clazz clazz = ioc.getBean("clazzInner", Clazz.class);
    System.out.println(clazz);
}

输出结果

org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'clazzInner' available

 分析

  • 关键点

    • 内部 Bean 只能在当前 Bean 的内部使用,无法通过 IOC 容器直接获取。

    • 即使为内部 Bean 指定了 id,也无法通过 ioc.getBean() 获取。

  • 结果

    • 抛出 NoSuchBeanDefinitionException 异常。

2025/2/26-11:12

六、依赖注入之为数组类型的属性赋值

在 Spring 中,可以通过 <array> 标签为数组类型的属性赋值。以下是详细解析和示例。


1. spring-ioc.xml 配置
<bean id="studentFive" class="com.atguigu.spring.pojo.Student">
    <property name="sid" value="1004"></property>
    <property name="sname" value="赵六"></property>
    <property name="age" value="26"></property>
    <property name="gender" value="男"></property>
    <!-- 为数组类型的 hobby 属性赋值 -->
    <property name="hobby">
        <array>
            <value>抽烟</value>
            <value>喝酒</value>
            <value>烫头</value>
        </array>
    </property>
    <!-- 内部 Bean -->
    <property name="clazz">
        <bean id="clazzInner" class="com.atguigu.spring.pojo.Clazz">
            <property name="cid" value="2222"></property>
            <property name="cname" value="远大前程"></property>
        </bean>
    </property>
</bean>

解析

  • <array> 标签

    • 用于为数组类型的属性赋值。

    • 每个 <value> 标签表示数组中的一个元素。

  • hobby 属性

    • 在 Student 类中,hobby 是一个数组类型的属性(如 String[])。

    • 通过 <array> 标签为其赋值,值为 ["抽烟", "喝酒", "烫头"]

  • 内部 Bean

    • clazz 属性通过内部 Bean 的方式赋值,值为 Clazz{cid=2222, cname='远大前程'}


2. Student 类

public class Student {
    private Integer sid;      // 学生 ID
    private String sname;     // 学生姓名
    private Integer age;      // 学生年龄
    private String gender;    // 学生性别
    private Double score;     // 学生成绩
    private String[] hobby;   // 学生爱好(数组类型)
    private Clazz clazz;      // 学生所属班级

    // Getter 和 Setter 方法
    public Integer getSid() {
        return sid;
    }

    public void setSid(Integer sid) {
        this.sid = sid;
    }

    public String getSname() {
        return sname;
    }

    public void setSname(String sname) {
        this.sname = sname;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public Double getScore() {
        return score;
    }

    public void setScore(Double score) {
        this.score = score;
    }

    public String[] getHobby() {
        return hobby;
    }

    public void setHobby(String[] hobby) {
        this.hobby = hobby;
    }

    public Clazz getClazz() {
        return clazz;
    }

    public void setClazz(Clazz clazz) {
        this.clazz = clazz;
    }

    @Override
    public String toString() {
        return "Student{" +
                "sid=" + sid +
                ", sname='" + sname + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                ", score=" + score +
                ", hobby=" + Arrays.toString(hobby) +
                ", clazz=" + clazz +
                '}';
    }
}

解析

  • hobby 属性

    • 类型为 String[],用于存储学生的多个爱好。

  • clazz 属性

    • 类型为 Clazz,表示学生所属的班级。


3. 测试代码
@Test
public void testDI() {
    // 获取 IOC 容器
    ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-ioc.xml");
    // 获取 Bean
    Student student = ioc.getBean("studentFive", Student.class);
    System.out.println(student);
}

4. 输出结果
Student{sid=1004, sname='赵六', age=26, gender='男', score=null, hobby=[抽烟, 喝酒, 烫头], clazz=Clazz{cid=2222, cname='远大前程'}}

 解析

  • hobby 属性

    • 成功注入了数组值 ["抽烟", "喝酒", "烫头"]

  • clazz 属性

    • 成功注入了内部 Bean,值为 Clazz{cid=2222, cname='远大前程'}


5. 分析

关键点

  1. 数组类型属性赋值

    • 使用 <array> 标签可以为数组类型的属性赋值。

    • 每个 <value> 标签表示数组中的一个元素。

  2. 内部 Bean

    • 内部 Bean 只能在当前 Bean 的内部使用,无法通过 IOC 容器直接获取。

  3. 类型匹配

    • 确保 hobby 属性的类型与配置中的赋值类型一致(如 String[])。

优点

  • 灵活性

    • 可以轻松为数组类型的属性赋值,支持多个值。

  • 可读性

    • 使用 <array> 标签使配置更加直观和易读。

2025/2/26-12:28:03

七、依赖注入之为 List 集合类型的属性赋值

演示一:直接使用 <list> 标签

1. spring-ioc.xml 配置
<bean id="clazzOne" class="com.atguigu.spring.pojo.Clazz">
    <property name="cid" value="1111"></property>
    <property name="cname" value="最强王者班"></property>
    <!-- 为 List 类型的 students 属性赋值 -->
    <property name="students">
        <list>
            <ref bean="studentOne"></ref>
            <ref bean="studentTwo"></ref>
            <ref bean="studentThree"></ref>
        </list>
    </property>
</bean>
2. Clazz 类
public class Clazz {
    private Integer cid;      // 班级 ID
    private String cname;     // 班级名称
    private List<Student> students; // 学生列表

    // Getter 和 Setter 方法
    public Integer getCid() {
        return cid;
    }

    public void setCid(Integer cid) {
        this.cid = cid;
    }

    public String getCname() {
        return cname;
    }

    public void setCname(String cname) {
        this.cname = cname;
    }

    public List<Student> getStudents() {
        return students;
    }

    public void setStudents(List<Student> students) {
        this.students = students;
    }

    @Override
    public String toString() {
        return "Clazz{" +
                "cid=" + cid +
                ", cname='" + cname + '\'' +
                ", students=" + students +
                '}';
    }
}
3. 测试代码
@Test
public void testDI() {
    // 获取 IOC 容器
    ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-ioc.xml");
    // 获取 Bean
    Clazz clazz = ioc.getBean("clazzOne", Clazz.class);
    System.out.println(clazz);
}
4. 输出结果
Clazz{cid=1111, cname='最强王者班', students=[Student{sid=null, sname='null', age=null, gender='null', score=null, hobby=null, clazz=null}, Student{sid=1001, sname='张三', age=23, gender='男', score=null, hobby=null, clazz=null}, Student{sid=1002, sname='李四', age=24, gender='女', score=null, hobby=null, clazz=null}]}
5. 分析
  • <list> 标签

    • 用于为 List 集合类型的属性赋值。

    • 每个 <ref> 标签表示 List 中的一个元素,引用其他 Bean。

  • students 属性

    • 成功注入了 List<Student>,包含 studentOnestudentTwo 和 studentThree

  • 注意

    • 如果 studentOnestudentTwo 和 studentThree 的某些属性未赋值,输出结果中会显示为 null


演示二:使用 <util:list> 标签

1. spring-ioc.xml 配置
<!-- 引入 util 命名空间 -->
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/util
                           http://www.springframework.org/schema/util/spring-util.xsd">

    <bean id="clazzOne" class="com.atguigu.spring.pojo.Clazz">
        <property name="cid" value="1111"></property>
        <property name="cname" value="最强王者班"></property>
        <!-- 引用外部的 List Bean -->
        <property name="students" ref="studentList"></property>
    </bean>

    <!-- 配置一个集合类型的 Bean -->
    <util:list id="studentList">
        <ref bean="studentOne"></ref>
        <ref bean="studentTwo"></ref>
        <ref bean="studentThree"></ref>
    </util:list>
</beans>
2. 测试代码
@Test
public void testDI() {
    // 获取 IOC 容器
    ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-ioc.xml");
    // 获取 Bean
    Clazz clazz = ioc.getBean("clazzOne", Clazz.class);
    System.out.println(clazz);
}
3. 输出结果
Clazz{cid=1111, cname='最强王者班', students=[Student{sid=null, sname='null', age=null, gender='null', score=null, hobby=null, clazz=null}, Student{sid=1001, sname='张三', age=23, gender='男', score=null, hobby=null, clazz=null}, Student{sid=1002, sname='李四', age=24, gender='女', score=null, hobby=null, clazz=null}]}
4. 分析
  • <util:list> 标签

    • 用于定义一个独立的 List Bean,可以在多个地方引用。

    • 需要引入 util 命名空间。

  • students 属性

    • 通过 ref="studentList" 引用外部的 List Bean。

    • 成功注入了 List<Student>,包含 studentOnestudentTwo 和 studentThree

  • 优点

    • 提高配置的复用性,适合多个 Bean 共享同一个集合。

八、依赖注入之为 Map 集合类型的属性赋值

1. spring-ioc.xml 配置
<bean id="studentFive" class="com.atguigu.spring.pojo.Student">
    <property name="sid" value="1004"></property>
    <property name="sname" value="赵六"></property>
    <property name="age" value="26"></property>
    <property name="gender" value="男"></property>
    <!-- 为 Map 类型的 teacherMap 属性赋值 -->
    <property name="teacherMap">
        <map>
            <entry key="10086" value-ref="teacherOne"></entry>
            <entry key="10010" value-ref="teacherTwo"></entry>
        </map>
    </property>
</bean>

<!-- 定义 Teacher Bean -->
<bean id="teacherOne" class="com.atguigu.spring.pojo.Teacher">
    <property name="tid" value="10086"></property>
    <property name="tname" value="大宝"></property>
</bean>

<bean id="teacherTwo" class="com.atguigu.spring.pojo.Teacher">
    <property name="tid" value="10010"></property>
    <property name="tname" value="二宝"></property>
</bean>

解析

  • <map> 标签

    • 用于为 Map 集合类型的属性赋值。

    • 每个 <entry> 标签表示 Map 中的一个键值对。

      • key:键的值。

      • value-ref:引用其他 Bean 作为值。

  • teacherMap 属性

    • 在 Student 类中,teacherMap 是一个 Map 类型的属性(如 Map<String, Teacher>)。

    • 通过 <map> 标签为其赋值,值为 {"10086": teacherOne, "10010": teacherTwo}


2. Student 类

public class Student {
    private Integer sid;      // 学生 ID
    private String sname;     // 学生姓名
    private Integer age;      // 学生年龄
    private String gender;    // 学生性别
    private Map<String, Teacher> teacherMap; // 教师 Map

    // Getter 和 Setter 方法
    public Integer getSid() {
        return sid;
    }

    public void setSid(Integer sid) {
        this.sid = sid;
    }

    public String getSname() {
        return sname;
    }

    public void setSname(String sname) {
        this.sname = sname;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getGender() {
        return gender;
    }

    public void setGender(String gender) {
        this.gender = gender;
    }

    public Map<String, Teacher> getTeacherMap() {
        return teacherMap;
    }

    public void setTeacherMap(Map<String, Teacher> teacherMap) {
        this.teacherMap = teacherMap;
    }

    @Override
    public String toString() {
        return "Student{" +
                "sid=" + sid +
                ", sname='" + sname + '\'' +
                ", age=" + age +
                ", gender='" + gender + '\'' +
                ", teacherMap=" + teacherMap +
                '}';
    }
}

解析

  • teacherMap 属性

    • 类型为 Map<String, Teacher>,用于存储学生的教师信息。

    • 键为教师 ID(String 类型),值为 Teacher 对象。


3. Teacher 类

public class Teacher {
    private Integer tid;      // 教师 ID
    private String tname;     // 教师姓名

    // Getter 和 Setter 方法
    public Integer getTid() {
        return tid;
    }

    public void setTid(Integer tid) {
        this.tid = tid;
    }

    public String getTname() {
        return tname;
    }

    public void setTname(String tname) {
        this.tname = tname;
    }

    @Override
    public String toString() {
        return "Teacher{" +
                "tid=" + tid +
                ", tname='" + tname + '\'' +
                '}';
    }
}

4. 测试代码

@Test
public void testDI() {
    // 获取 IOC 容器
    ApplicationContext ioc = new ClassPathXmlApplicationContext("spring-ioc.xml");
    // 获取 Bean
    Student student = ioc.getBean("studentFive", Student.class);
    System.out.println(student);
}

5. 输出结果

Student{sid=1004, sname='赵六', age=26, gender='男', teacherMap={10086=Teacher{tid=10086, tname='大宝'}, 10010=Teacher{tid=10010, tname='二宝'}}}

6. 分析

关键点

  1. <map> 标签

    • 用于为 Map 集合类型的属性赋值。

    • 每个 <entry> 标签表示 Map 中的一个键值对。

  2. teacherMap 属性

    • 成功注入了 Map<String, Teacher>,包含两个键值对:

      • "10086" 对应 Teacher{tid=10086, tname='大宝'}

      • "10010" 对应 Teacher{tid=10010, tname='二宝'}

  3. 类型匹配

    • 确保 teacherMap 属性的类型与配置中的赋值类型一致(如 Map<String, Teacher>)。

优点

  • 灵活性

    • 可以轻松为 Map 类型的属性赋值,支持复杂的键值对结构。

  • 可读性

    • 使用 <map> 标签使配置更加直观和易读。

九、依赖注入之 p 命名空间

1. 简介

  • 目的:简化 XML 配置,通过属性(而非嵌套标签)注入依赖。

  • 适用场景:适用于简单属性(基本类型、字符串)或直接 Bean 引用。

2. 配置示例

<!-- 传统方式 -->
<bean id="student" class="com.example.Student">
    <property name="sname" value="张三"/>
    <property name="teacher" ref="teacherOne"/>
</bean>

<!-- 使用 p 命名空间 -->
<bean id="student" class="com.example.Student" 
    p:sname="张三" 
    p:teacher-ref="teacherOne"/>

3. 关键点

  • 启用 p 命名空间:需在 XML 头部添加 xmlns:p="http://www.springframework.org/schema/p"

  • 语法规则

    • 基本类型:p:属性名="值"

    • Bean 引用:p:属性名-ref="Bean ID"

  • 局限性:不支持复杂类型(如 Map、List),需结合传统 <property> 标签使用。

4. 优点

  • 简洁性:减少嵌套标签,提升可读性。

  • 直观性:属性直接对应类字段,配置更直观。

这两天太浮躁摆烂了,学不下去,今天(2025/2/26-22:22:22)没怎么学习,自我安慰......

明天真要好好开始认真学习了,补回来QAQ......