3、Spring 中的依赖注入(DI),你都知道多少?

简介: 3、Spring 中的依赖注入(DI),你都知道多少?

0. 前言

Spring 中,用来组成应用程序的主体以及由 Spring IoC 容器所管理的对象叫做 Bean。简而言之,Bean 就是由 IoC 容器来进行初始化、装配和管理的对象。


Bean 的作用域主要有如下几种:


0.1 Singleton

作用域为 Singleton,表明 IoC 容器中只会存在一个共享 Bean 实例,而且所有对 Bean 的请求,主要 id 和该 Bean 定义相匹配,那么就会返回 Bean 的同一实例。Singleton 是单例模型,即在从创建容器的同时就会自动创建一个 Bean 的对象,无论是否使用,而且每次获取到的对象都是同一对象。


0.2 Prototype

作用域为 Prototype,表明一个 Bean 定义对应多个实例,该作用域中的 Bean 会导致在每次对该 Bean 请求时均创建一个新的 Bean 实例。Prototype 是一个原型类型,在我们创建容器时并未实例化,而是当我们获取 Bean 时才去创建一个对象,而且每次获取到的对象都不一样。


0.3 Request

作用域为 Request,表明在一次 HTTP 请求中,一个 Bean 对应一个实例,即每个 HTTP 请求均有各自的 Bean 实例,依据某个 Bean 定义创建而成,只在基于 Web 的 Spring ApplicationContext 情形下有效。当一次 HTTP 请求处理结束时,该作用域中的 Bean 实例均被销毁。


0.4 Session

作用域为 Session ,表明在一个 HTTP Session 中,一个 Bean 对应一个实例,只在基于 Web 的 Spring ApplicationContext 情形下有效。当一个 HTTP Session 被废弃时,在该作用域内的 Bean 也将失效。


作用域类别 说明

Singleton Spring IoC 容器中仅存在一个 Bean 实例,以单例方式存在,是 Spring 中的默认值

Prototype 每次从容器中调用 Bean 时,均返回一个新的实例,即每次调用 getBean() 方法,相当于 new 一个新的对象

Request 每次 HTTP 请求均创建一个新的 Bean,仅适用于 WebApplicationContext 环境

Session 每次 HTTP Session 共享一个 Bean,不同 Session 使用不同的 Bean,仅适用于 WebApplicationContext 环境

1. 什么是 DI

DI(Dependency Injection),即依赖注入。其中 依赖指的是 Bean 对象的创建依赖于容器,是 Bean 对象的依赖资源;而注入则指的是 Bean 对象所以来的资源由容器来设置和装配 。


2. 实现 DI 的方式

要实现依赖注入,通常有如下几种方法:


构造器注入

Set 注入

p 命名和 c 命名注入

2.1 构造器注入

由于构造器可以分为无参和有参构造器,所有又可以分为 有参构造器注入 和 无参构造器注入。


2.1.1 无参构造器注入

首先创建实体类 User


package com.cunyu.pojo;
/**
 * @author : cunyu
 * @version : 1.0
 * @className : User
 * @date : 2020/7/17 14:51
 * @description : TODO
 */
public class User {
    private String name;
    public User() {
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void sayHello() {
        System.out.println("hello," + name);
    }
}
  1. 接着配置 Spring 配置文件,在 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 http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--  bean 即为 Java 对象,由 Spring 创建和管理  -->
    <bean id="user" class="com.cunyu.pojo.User">
        <property name="name" value="村雨遥"/>
    </bean>
</beans>
  1. 利用 Junit 进行单元测试
package com.cunyu.pojo;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
 * @author : cunyu
 * @version : 1.0
 * @className : HelloTest
 * @date : 2020/7/17 14:56
 * @description : Hello 测试类
 */
public class HelloTest {
    @Test
    public void testSayHello() {
//        解析 Spring 配置文件,生成管理相应的 Bean 对象
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
//      getBean() 方法的参数即为 Spring 配置文件中 bean 的 id
        User user = (User) applicationContext.getBean("user");
        user.sayHello();
    }
}

2.1.2 有参构造器注入

  1. 同样先创建一个实体类,同时添加有参构造器方法
package com.cunyu.pojo;
/**
 * @author : cunyu
 * @version : 1.0
 * @className : User
 * @date : 2020/7/17 14:51
 * @description : TODO
 */
public class User {
    private String name;
    public User(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void sayHello() {
        System.out.println("hello," + name);
    }
}

配置 Spring 配置文件

此时配置 Spring 配置文件有 3 种不同的方法:


通过 index 下标属性设置

<bean id="user" class="com.cunyu.pojo.User">

   <constructor-arg index="0" value="村雨遥"/>

</bean>


通过参数名设置

<bean id="user" class="com.cunyu.pojo.User">

   <constructor-arg name="name" value="村雨遥"/>

</bean>


通过参数类型设置

<bean id="user" class="com.cunyu.pojo.User">

   <constructor-arg type="java.lang.String" value="村雨遥"/>

</bean>


通过 Junit 测试


package com.cunyu.pojo;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
 * @author : cunyu
 * @version : 1.0
 * @className : HelloTest
 * @date : 2020/7/17 14:56
 * @description : Hello 测试类
 */
public class HelloTest {
    @Test
    public void testSayHello() {
//        解析 Spring 配置文件,生成管理相应的 Bean 对象
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
//      getBean() 方法的参数即为 Spring 配置文件中 bean 的 id
        User user = (User) applicationContext.getBean("user");
        user.sayHello();
    }
}

2.2 Set 注入

要注入某属性,则该属性必须有 set() 方法;

2.2.1 创建实体类

package com.cunyu.pojo;
/**
 * @author : cunyu
 * @version : 1.0
 * @className : Address
 * @date : 2020/7/17 16:10
 * @description : 地址类
 */
public class Address {
    private String address;
    public String getAddress() {
        return address;
    }
    public void setAddress(String address) {
        this.address = address;
    }
}
package com.cunyu.pojo;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.Map;
/**
 * @author : cunyu
 * @version : 1.0
 * @className : User
 * @date : 2020/7/17 14:51
 * @description : TODO
 */
public class User {
    private String name;
    private Address address;
    private String[] cars;
    private List<String> pets;
    private Map<String, String> cards;
    private Set<String> games;
    private String girlFriend;
    private Properties info;
    public String getName() {
        return name;
    }
    public Address getAddress() {
        return address;
    }
    public String[] getCars() {
        return cars;
    }
    public List<String> getPets() {
        return pets;
    }
    public Map<String, String> getCards() {
        return cards;
    }
    public Set<String> getGames() {
        return games;
    }
    public String getGirlFriend() {
        return girlFriend;
    }
    public Properties getInfo() {
        return info;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void setAddress(Address address) {
        this.address = address;
    }
    public void setCars(String[] cars) {
        this.cars = cars;
    }
    public void setPets(List<String> pets) {
        this.pets = pets;
    }
    public void setCards(Map<String, String> cards) {
        this.cards = cards;
    }
    public void setGames(Set<String> games) {
        this.games = games;
    }
    public void setGirlFriend(String girlFriend) {
        this.girlFriend = girlFriend;
    }
    public void setInfo(Properties info) {
        this.info = info;
    }
    public void display() {
        System.out.println("name = " + name + ", address = " + address.getAddress() + ", cars = ");
        for (String car : cars
        ) {
            System.out.print(car + "\t");
        }
        System.out.println("pets: " + pets);
        System.out.println("card:" + cards);
        System.out.println("games:" + games);
        System.out.println("gf:" + girlFriend);
        System.out.println("info:" + info);
    }
}

2.2.2 各类型属性注入

  1. 常量注入
<bean id="user" class="com.cunyu.pojo.User">
    <property name="name" value="村雨遥"/>
</bean>
• 1
• 2
• 3
  1. Bean 注入
<bean id="addr" class="com.cunyu.pojo.Address">
    <property name="address" value="贵州"/>
</bean>
<bean id="user" class="com.cunyu.pojo.User">
    <property name="name" value="村雨遥"/>
    <property name="address" ref="addr"/>
</bean>
  1. 数组注入
<bean id="user" class="com.cunyu.pojo.User">
    <property name="cars">
      <array>
            <value>奥迪</value>
            <value>小牛</value>
            <value>法拉利</value>
      </array>
    </property>
</bean>
  1. List 注入
<bean id="user" class="com.cunyu.pojo.User">
    <property name="pets">
      <list>
            <value>猫</value>
            <value>狗</value>
            <value>鼠</value>
      </list>
    </property>
</bean>
  1. Map 注入
<bean id="user" class="com.cunyu.pojo.User">
    <property name="cards">
      <map>
            <entry key="建行" value="12345678900"/>
            <entry key="工行" value="00987654321"/>
      </map>
    </property>
</bean>
  1. set 注入
<bean id="user" class="com.cunyu.pojo.User">
    <property name="games">
      <set>
            <value>GTA5</value>
            <value>Area of Honor</value>
            <value>PUGB</value>
      </set>
    </property>
</bean>
  1. Null 注入
<bean id="user" class="com.cunyu.pojo.User">
    <property name="girlFriend">
        <null/>
    </property>
</bean>
  1. Properties 注入


<bean id="user" class="com.cunyu.pojo.User">
    <property name="info">
        <props>
            <prop key="姓名">村雨遥</prop>
            <prop key="血型">B</prop>
        </props>
    </property>
</bean>

测试:

package com.cunyu.pojo;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
 * @author : cunyu
 * @version : 1.0
 * @className : HelloTest
 * @date : 2020/7/17 14:56
 * @description : Hello 测试类
 */
public class HelloTest {
    @Test
    public void test() {
//        解析 Spring 配置文件,生成管理相应的 Bean 对象
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
//      getBean() 方法的参数即为 Spring 配置文件中 bean 的 id
        User user = (User) applicationContext.getBean("user");
        user.display();
    }
}

image.png2.3 p 命名和 c 命名注入

2.3.1 p 命名注入

创建实体类和其他注入方式相同

配置 Spring 配置文件

首先需要在配置文件的头文件中加入约束条件:


xmlns:p="http://www.springframework.org/schema/p"


接着在配置文件中配置即可:


<bean id="user" class="com.cunyu.pojo.User" p:name="村雨遥" p:address="贵州"/>


测试方法同其他注入方式

2.3.2 c 命名注入

创建实体类和其他注入方式相同

配置 Spring 配置文件

首先需要在配置文件的头文件中加入约束条件:


xmlns:c="http://www.springframework.org/schema/c"


接着在配置文件中配置即可:


<bean id="user" class="com.cunyu.pojo.User" c:name="村雨遥" c:address="贵州"/>


测试方法同其他注入方式


目录
相关文章
|
6月前
|
Java 容器 Spring
什么是Spring IOC 和DI ?
IOC : 控制翻转 , 它把传统上由程序代码直接操控的对象的调用权交给容 器,通过容器来实现对象组件的装配和管理。所谓的“控制反转”概念就是对组件对象控制权的转 移,从程序代码本身转移到了外部容器。 DI : 依赖注入,在我们创建对象的过程中,把对象依赖的属性注入到我们的类中。
|
9月前
|
设计模式 XML Java
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
本文详细介绍了Spring框架的核心功能,并通过手写自定义Spring框架的方式,深入理解了Spring的IOC(控制反转)和DI(依赖注入)功能,并且学会实际运用设计模式到真实开发中。
【23种设计模式·全精解析 | 自定义Spring框架篇】Spring核心源码分析+自定义Spring的IOC功能,依赖注入功能
|
9月前
|
存储 Java 应用服务中间件
【Spring】IoC和DI,控制反转,Bean对象的获取方式
IoC,DI,控制反转容器,Bean的基本常识,类注解@Controller,获取Bean对象的常用三种方式
228 12
|
XML Java 测试技术
Spring Boot中的依赖注入和控制反转
Spring Boot中的依赖注入和控制反转
|
9月前
|
Java 数据库 数据安全/隐私保护
轻松掌握Spring依赖注入:打造你的登录验证系统
本文以轻松活泼的风格,带领读者走进Spring框架中的依赖注入和登录验证的世界。通过详细的步骤和代码示例,我们从DAO层的创建到Service层的实现,再到Spring配置文件的编写,最后通过测试类验证功能,一步步构建了一个简单的登录验证系统。文章不仅提供了实用的技术指导,还以口语化和生动的语言,让学习变得不再枯燥。
165 2
|
11月前
|
存储 开发框架 Java
什么是Spring?什么是IOC?什么是DI?IOC和DI的关系? —— 零基础可无压力学习,带源码
文章详细介绍了Spring、IOC、DI的概念和关系,解释了控制反转(IOC)和依赖注入(DI)的原理,并提供了IOC的代码示例,阐述了Spring框架作为IOC容器的应用。
728 1
什么是Spring?什么是IOC?什么是DI?IOC和DI的关系? —— 零基础可无压力学习,带源码
|
11月前
|
存储 Java 程序员
SpringIOC和DI的代码实现,Spring如何存取对象?@Controller、@Service、@Repository、@Component、@Configuration、@Bean DI详解
本文详细讲解了Spring框架中IOC容器如何存储和取出Bean对象,包括五大类注解(@Controller、@Service、@Repository、@Component、@Configuration)和方法注解@Bean的用法,以及DI(依赖注入)的三种注入方式:属性注入、构造方法注入和Setter注入,并分析了它们的优缺点。
189 0
SpringIOC和DI的代码实现,Spring如何存取对象?@Controller、@Service、@Repository、@Component、@Configuration、@Bean DI详解
|
Java 数据库连接 数据格式
【Java笔记+踩坑】Spring基础2——IOC,DI注解开发、整合Mybatis,Junit
IOC/DI配置管理DruidDataSource和properties、核心容器的创建、获取bean的方式、spring注解开发、注解开发管理第三方bean、Spring整合Mybatis和Junit
【Java笔记+踩坑】Spring基础2——IOC,DI注解开发、整合Mybatis,Junit
|
Java 数据库连接 Maven
Spring基础1——Spring(配置开发版),IOC和DI
spring介绍、入门案例、控制反转IOC、IOC容器、Bean、依赖注入DI
Spring基础1——Spring(配置开发版),IOC和DI
|
设计模式 自然语言处理 Java
简单了解下Spring中的各种Aware接口实现依赖注入
在Spring框架中,Aware接口是一组用于提供特定资源或环境信息的回调接口。这些接口被设计用来允许Bean获取对Spring容器或其他相关资源的引用,并在需要时进行适当的处理。
165 2