程序员社区

11. Spring 依赖注入

Spring 依赖注入

  上文介绍了如何在 spring.xml 文件中配置一个 bean 对象,但是当时所使用的属性都是基本数据类型和 String 字符串类型,那么如何将一个类的实例化对象注入到另一个类的对象中呢?这就是依赖注入(Dependency Injection)的问题,本文主要讲解的是如何在 XML 文件中完成对象的依赖注入

1. 依赖注入(DI)

  假如现在有这样的一个应用场景,建立学生信息类与家庭住址类的关联,我们很直观会想到创建 Student 类和 Address 类,然后会在 Student 类中新增一个 Address 类型的私有属性,最后在创建 student 对象之前,先创建 address 对象,然后通过有参构造或者 setAddress() 方法来完成对象的注入。

  但现在我们知道:在Spring 框架中,对象只通过 XML 文件来配置,不需要开发者自己 new 来创建,那么如何在 XML 配置文件中绑定两个对象呢?下面通过实例代码来说明。

1、创建实体类 Address 和 Student

package com.trainingl.entity;

import lombok.Data;

@Data
public class Address {
    private Integer id;
    private String city;
}
package com.trainingl.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
    private Integer id;
    private String name;
    private Double score;
    private Address address;
}

2、在 spring.xml 中配置 Student 和 Address 的 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"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
	   http://www.springframework.org/schema/context
	   http://www.springframework.org/schema/context/spring-context-4.3.xsd">
    <bean id="student" class="com.trainingl.entity.Student">
        <property name="id" value="1"></property>
        <property name="name" value="小明"></property>
        <property name="score" value="90"></property>
        <property name="address" ref="addr"></property>
    </bean>

    <bean id="addr" class="com.trainingl.entity.Address">
       <property name="id" value="1"></property>
        <property name="city" value="武汉"></property>
    </bean>
</beans>
  • 通过配置 bean 标签完成对象的管理;
    • id:对象标识符(唯一)
    • class:对象的模板类(所有交给 IoC容器来管理的类必须有无参构造方法,因为 Spring 底层是通过反射机制来创建对象,调用的是无参构造方法)
  • 对象的成员变量通过 property 标签完成对象属性的赋值操作;
    • name:成员变量名
    • value:成员变量值(基本数据类型、String 可以直接赋值,如果是其他引用类型,不能通过 value 赋值)
    • ref:将 IoC 中的另外一个 bean 赋值给当前 bean 的成员变量(被称为依赖注入)

在这里插入图片描述

​ ​ 这样就可以将 Address 的实例化对象与 student 对象关联起来,也可以说是将 address 对象注入到了 student 对象中,其实只需要使用到 ref 属性 id 即可。

3、测试类中获取 student 对象

package com.trainingl.test;

import com.trainingl.entity.Student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test2 {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        Student student = (Student)applicationContext.getBean("student");
        System.out.println(student);
    }
}

在这里插入图片描述


2. IOC 自动装载

依赖注入的方式,除了通过配置 property 的 ref 属性将 bean 进行注入外,Spring 还提供了另外一种更加简便的方式——自动装置,不需要手动配置 property,IOC容器会自动选择 bean 完成依赖注入


11. Spring 依赖注入插图2

自动装置有两种方式:

  1. byName:通过属性名自动装载;
  2. byType:通过属性对应的数据类型自动装载;

1、创建实体类 Car 和 Student

package com.trainingl.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Car {
    private int num;
    private String brand;
}
package com.trainingl.entity;

import lombok.Data;

@Data
public class Person {
    private Integer id;
    private String name;
    private Car car;
}

2、spring.xml 中配置 Car 和 Person 的 bean 标签,并通过自动装载进行依赖注入

byName:通过属性名自动装载

<?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:context="http://www.springframework.org/schema/context"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
	   http://www.springframework.org/schema/context
	   http://www.springframework.org/schema/context/spring-context-4.3.xsd
">
    <!--自动装载-->
    <bean id="car" class="com.trainingl.entity.Car">
        <property name="num" value="22"></property>
        <property name="brand" value="本田"></property>
    </bean>

    <bean id="person" class="com.trainingl.entity.Person" autowire="byName">
        <property name="id" value="1"></property>
        <property name="name" value="张三"></property>
        <!--创建person对象时,没有在property中配置car属性,所以IOC容器会自动进行装载-->
    </bean>
</beans>

创建 person 对象时,没有在 property 中配置 car 属性,所以 IOC 容器会自动进行装载,autowire = "byName" 表示匹配属性名的方式去装载对应的 bean,Person 实体类中有 car 属性,所以就将 id=car 的 bean 注入到 person 对应的 bean中。

注意:通过 property 标签手动进行 car 的注入优先级更高,即:<property name="car" ref="car"></property> 也存在时,以 property 的配置为准。

3、测试类中获取 person 对象

package com.trainingl.test;

import com.trainingl.entity.Car;
import com.trainingl.entity.Person;
import com.trainingl.entity.Student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test2 {
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        Person person = (Person)applicationContext.getBean("person");
        System.out.println(person);
    }
}

在这里插入图片描述

当然,也可以通过 byType 即属性的数据类型来配置

<?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:context="http://www.springframework.org/schema/context"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
	   http://www.springframework.org/schema/context
	   http://www.springframework.org/schema/context/spring-context-4.3.xsd
">
    <!--自动装载-->
    <bean id="car1" class="com.trainingl.entity.Car">
        <property name="num" value="22"></property>
        <property name="brand" value="本田"></property>
    </bean>
    <bean id="car2" class="com.trainingl.entity.Car">
        <property name="num" value="23"></property>
        <property name="brand" value="丰田"></property>
    </bean>

    <bean id="person" class="com.trainingl.entity.Person" autowire="byType">
        <property name="id" value="1"></property>
        <property name="name" value="张三"></property>
        <!--创建person对象时,没有在property中配置car属性,所以IOC容器会自动进行装载-->
    </bean>
</beans>

但需要注意的是,使用 byType 进行自动装载时,如果在 spring.xml 中配置两个或以上 Car 类型的 bean时,IOC容器就不知道应该将哪个 bean 装载到 person 对象中,所以会有如下的报错提示:

在这里插入图片描述

因此,使用 byType 进行自动装载时,spring.xml 中只能配置一个指定数据类型装载的 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"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
	   http://www.springframework.org/schema/context
	   http://www.springframework.org/schema/context/spring-context-4.3.xsd
">
    <!--自动装载-->
    <bean id="car1" class="com.trainingl.entity.Car">
        <property name="num" value="22"></property>
        <property name="brand" value="本田"></property>
    </bean>

    <bean id="person" class="com.trainingl.entity.Person" autowire="byType">
        <property name="id" value="1"></property>
        <property name="name" value="张三"></property>
        <!--创建person对象时,没有在property中配置car属性,所以IOC容器会自动进行装载-->
    </bean>
</beans>

同样地,在测试类中获取 person 对象。

在这里插入图片描述
本文通过实例介绍了XML配置文件两种依赖注入,一个是基于 ref 的 JavaBean 注入,另外一个是基于 autowire 的自动装载,可能因为注解的出现,以上两种方式并不常用了,但是对于理解和学习都是很有帮助的。

赞(0) 打赏
未经允许不得转载:IDEA激活码 » 11. Spring 依赖注入

一个分享Java & Python知识的社区