Spring的依赖注入

本文深入讲解Spring框架中的依赖注入概念,包括三种主要的注入方式:构造函数注入、setter方法注入和复杂类型/集合类型注入。并通过示例代码详细解析每种注入方式的使用场景和优缺点。

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

依赖注入的概念

  • 依赖注入:Dependency Injection。它是 spring 框架核心IOC的具体实现。
  • IOC的作用:降低程序中的耦合(依赖关系),但是绝不可能消除。

我们的程序在编写时,通过控制反转,把对象的创建交给了 spring,但是代码中不可能出现没有依赖的情况。例如:我们的业务层仍会调用持久层的方法。这种业务层和持久层的依赖关系,在使用 spring 之后,就让 spring 来维护了。
简单的说,就是坐等框架把持久层对象传入业务层,而不用我们自己去获取。

注入数据的类型

有三类:

  1. 基本数据类型和String
  2. 其他bean类型(在配置文件或者注解中配置过得bean)
  3. 复杂类型/集合类型

一、构造函数注入

编写业务层实现类的构造函数

/**
 1. 账户的业务层实现类
 */
public class AccountServiceImpl implements IAccountService {

    //private IAccountDao accountDao = new AccountDaoImpl();
    private String name;
    private Integer age;
    private Date birthday;

    public AccountServiceImpl(String name, Integer age, Date birthday) {
        this.name = name;
        this.age = age;
        this.birthday = birthday;
    }
    @Override
    public void  saveAccount(){
        System.out.println(name +"\n"+ age +"\n"+ birthday);
    }
}

在bean.xml中注入数据

使用构造函数的方式,给 service 中的属性传值
要求:

  • 类中需要提供一个对应参数列表的构造函数。
  • 涉及的标签:constructor-arg

属性:

  1. 给谁赋值:
  • index:指定参数在构造函数参数列表的索引位置
  • type:指定参数在构造函数中的数据类型
  • name:指定参数在构造函数中的名称,用这个找给谁赋值
  1. 赋什么值:
  • value:它能赋的值是基本数据类型和 String 类型
  • ref:它能赋的值是其他 bean 类型,也就是说,必须得是在配置文件中配置过的 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
        http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="accountServer" class="com.java.service.impl.AccountServiceImpl">
    <constructor-arg name="name" index="0" value="张三"></constructor-arg>
    <constructor-arg name="age" index="1" value="18"></constructor-arg>
    <constructor-arg name="birthday" index="2" ref="time"></constructor-arg>
</bean>
<bean id="time" class="java.util.Date"></bean>

这里有一个注意的点:birthday是Date类型的数据,而value属性中的值默认是字符串,因此这里不能直接写时间,而应该使用ref关联一个配置过的bean来表示时间。

测试

/**
 * 模拟一个表现层,用于调用业务层
 */
public class Client {

    public static void main(String[] args) {
      //1、获取容器对象
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
      //2、根据id获取Bean对象
        IAccountService as = (IAccountService)ac.getBean("accountServer");
        IAccountDao ad = ac.getBean("accountDao",IAccountDao.class);
        as.saveAccount();
        //as.saveAccount();
    }
}

运行结果:
构造方法注入运行结果
使用构造函数注入的优劣:

  • 优势:在获取bean对象时,注入数据是必须的操作,否则无法创建对象
  • 弊端:改变了bean对象的实例化方法,当创建对象时,即使用不到这些数据,也必须提供。

二、set方法注入

生成业务层实现类的Setter方法

/**
 * 账户的业务层实现类
 */
public class AccountServiceImpl implements IAccountService {

    private String name;
    private Integer age;
    private Date birthday;

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

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    @Override
    public void  saveAccount(){
        System.out.println(name +"\n"+ age +"\n"+ birthday);
    }
}

在bean.xml中注入数据

通过配置文件给 bean 中的属性传值:使用 set 方法的方式
涉及的标签:property
属性:

  • name:找的是类中 set 方法后面的部分
  • ref:给属性赋值是其他 bean 类型的
  • value:给属性赋值是基本数据类型和 string 类型的
    使用Set方法注入的优劣:
  • 优势:创建对象时没有明确的限制,可以直接使用默认构造函数
  • 弊端:当某个对象必须有值,在获取对象时有可能出现set方法没有执行的情况
<?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 id="accountServer" class="com.itheima.service.impl.AccountServiceImpl">
        <property name="name" value="李四"></property>
        <property name="age" value="19"></property>
        <property name="birthday" ref="time"></property>
    </bean>
    <bean id="time" class="java.util.Date"></bean>
</beans>

测试

原先的表现层代码原封不动,运行结果如下:
set方法注入结果

三、复杂类型/集合类型注入

编写业务层实现类的复杂类型和集合类型,生成set方法

/**
 * 账户的业务层实现类
 */
public class AccountServiceImpl implements IAccountService {

    private String[] myStrs;
    private List<String> myList;
    private Set<String> mySet;
    private Map<String,String> myMap;
    private Properties myProps;

    public void setMyStrs(String[] myStrs) {
        this.myStrs = myStrs;
    }

    public void setMyList(List<String> myList) {
        this.myList = myList;
    }

    public void setMySet(Set<String> mySet) {
        this.mySet = mySet;
    }

    public void setMyMap(Map<String, String> myMap) {
        this.myMap = myMap;
    }

    public void setMyProps(Properties myProps) {
        this.myProps = myProps;
    }

    @Override
    public void  saveAccount(){
        System.out.println(Arrays.toString(myStrs));
        System.out.println(myList);
        System.out.println(mySet);
        System.out.println(myMap);
        System.out.println(myProps);
    }
}

在bean.xml中注入数据

  • List 结构的:
    array,list,set
  • Map 结构的
    map,entry,props,prop
<?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 id="accountServer" class="com.itheima.service.impl.AccountServiceImpl">
        <!-- 在注入集合数据时,只要结构相同,标签可以互换 -->
        <!-- 给数组注入数据 -->
        <property name="myStrs">
            <set>
                <value>AAA</value>
                <value>BBB</value>
                <value>CCC</value>
             </set>
    </property>
        <!-- 注入 list 集合数据 -->
        <property name="myList">
            <array>
                <value>AAA</value>
                <value>BBB</value>
                <value>CCC</value>
            </array>
    </property>
        <!-- 注入 set 集合数据 -->
        <property name="mySet">
            <list><value>AAA</value> <value>BBB</value> <value>CCC</value>
    </list>
    </property>
        <!-- 注入 Map 数据 -->
        <property name="myMap">
            <props>
                <prop key="testA">aaa</prop>
                <prop key="testB">bbb</prop>
    </props>
    </property>
        <!-- 注入 properties 数据 -->
        <property name="myProps">
            <map>
                <entry key="testA" value="aaa"></entry>
                    <entry key="testB">
                        <value>bbb</value>
                    </entry>
            </map>
        </property>
    </bean>
</beans>

测试

原先的表现层代码原封不动,运行结果如下:
复杂类型和集合类型的注入结果


本文结束。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值