[Spring Framework]DI依赖注入①

举报
十八岁讨厌编程 发表于 2022/08/05 23:13:59 2022/08/05
【摘要】 文章目录 引入Setter注入引用数据类型简单数据类型 构造器注入引用数据类型简单数据类型优化方案一优化方案二 依赖注入方式的选择总结 引入 如果我们要向类中传递数据,我们要借助于...

引入

如果我们要向类中传递数据,我们要借助于方法往里面传,这是肯定的。但是这个方法是可以有多种的。于是这里就分出来两种:

  • 普通方法(set方法)
  • 构造方法

然后我们再思考:依赖注入描述了在容器中建立bean与bean之间依赖关系的过程,那么如果bean运行需要的是数字或字符串呢?

也就是说我们可以再次细分:

  • setter注入
    • 简单数据类型
    • 引用数据类型
  • 构造器注入
    • 简单数据类型
    • 引用数据类型

Setter注入

引用数据类型

我们之前使用的就是这种,所以我们复习一下:

  • 在bean中定义引用类型属性,并提供可访问的set方法
public class BookServiceImpl implements BookService {
    private BookDao bookDao;
    public void setBookDao(BookDao bookDao) {
        this.bookDao = bookDao;
    }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 配置中使用property标签ref属性注入引用类型对象
<bean id="bookService" class="impl.BookServiceImpl">
	<property name="bookDao" ref="bookDao"/>
</bean>

<bean id="bookDao" class="imipl.BookDaoImpl"/>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

简单数据类型

简单数据类型与引用数据类型差不多,区别在于配置的时候不再使用ref,而是使用value

我们接下来举一个例子:

步骤1:声明属性并提供setter方法

在BookDaoImpl类中声明对应的简单数据类型的属性,并提供对应的setter方法

public class BookDaoImpl implements BookDao {

    private String databaseName;
    private int connectionNum;

    public void setConnectionNum(int connectionNum) {
        this.connectionNum = connectionNum;
    }

    public void setDatabaseName(String databaseName) {
        this.databaseName = databaseName;
    }

    public void save() {
        System.out.println("book dao save ..."+databaseName+","+connectionNum);
    }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

步骤2:配置文件中进行注入配置

在applicationContext.xml配置文件中使用property标签注入

<?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="bookDao" class="impl.BookDaoImpl">
        <property name="databaseName" value="mysql"/>
     	<property name="connectionNum" value="10"/>
    </bean>
    <bean id="userDao" class="impl.UserDaoImpl"/>
    <bean id="bookService" class="impl.BookServiceImpl">
        <property name="bookDao" ref="bookDao"/>
        <property name="userDao" ref="userDao"/>
    </bean>
</beans>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

两个property注入标签的顺序可以任意。

结果:
在这里插入图片描述

注意:
value:后面跟的是简单数据类型,对于参数类型,Spring在注入的时候会自动转换,但是不能写成

<property name="connectionNum" value="abc"/>

  
 
  • 1

这样的话,spring在将abc转换成int类型的时候就会报错。

对于setter注入方式的基本使用就已经介绍完了,

  • 对于引用数据类型使用的是<property name="" ref=""/>
  • 对于简单数据类型使用的是<property name="" value=""/>

构造器注入

引用数据类型

步骤1:删除setter方法并提供构造方法

在BookServiceImpl类中将bookDao的setter方法删除掉,并添加带有bookDao参数的构造方法

public class BookServiceImpl implements BookService{
    private BookDao bookDao;

    public BookServiceImpl(BookDao bookDao) {
        this.bookDao = bookDao;
    }

    public void save() {
        System.out.println("book service save ...");
        bookDao.save();
    }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

步骤2:配置文件中进行配置构造方式注入

在Spring配置文件中配置

<?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="bookDao" class="impl.BookDaoImpl"/>
    <bean id="bookService" class="impl.BookServiceImpl">
        <constructor-arg name="bookDao" ref="bookDao"/>
    </bean>
</beans>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

说明:

标签中

  • name属性对应的值为构造函数中方法形参的参数名,必须要保持一致。

  • ref属性指向的是spring的IOC容器中其他bean对象。

简单数据类型

步骤1:添加多个简单属性并提供构造方法

修改BookDaoImpl类,添加构造方法

public class BookDaoImpl implements BookDao {
    private String databaseName;
    private int connectionNum;

    public BookDaoImpl(String databaseName, int connectionNum) {
        this.databaseName = databaseName;
        this.connectionNum = connectionNum;
    }

    public void save() {
        System.out.println("book dao save ..."+databaseName+","+connectionNum);
    }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

步骤2:配置完成多个属性构造器注入

在Spring配置文件中进行注入配置:

<?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="bookDao" class="impl.BookDaoImpl">
        <constructor-arg name="databaseName" value="mysql"/>
        <constructor-arg name="connectionNum" value="666"/>
    </bean>
    <bean id="userDao" class="impl.UserDaoImpl"/>
    <bean id="bookService" class="impl.BookServiceImpl">
        <constructor-arg name="bookDao" ref="bookDao"/>
        <constructor-arg name="userDao" ref="userDao"/>
    </bean>
</beans>

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

说明:这两个<contructor-arg>的配置顺序可以任意

上面已经完成了构造函数注入的基本使用,但是会存在一些问题:
在这里插入图片描述

当构造函数中方法的参数名发生变化后,配置文件中的name属性也需要跟着变,这两块存在紧耦合,具体该如何解决?

在解决这个问题之前,需要提前说明的是,这个参数名发生变化的情况并不多,所以上面的还是比较主流的配置方式,下面介绍的,大家都以了解为主。

优化方案一

删除name属性,添加type属性,按照类型注入

<bean id="bookDao" class="impl.BookDaoImpl">
    <constructor-arg type="int" value="10"/>
    <constructor-arg type="java.lang.String" value="mysql"/>
</bean>

  
 
  • 1
  • 2
  • 3
  • 4
  • 这种方式可以解决构造函数形参名发生变化带来的耦合问题
  • 但是如果构造方法参数中有类型相同的参数,这种方式就不太好实现了

优化方案二

删除type属性,添加index属性,按照索引下标注入,下标从0开始

<bean id="bookDao" class="impl.BookDaoImpl">
    <constructor-arg index="1" value="100"/>
    <constructor-arg index="0" value="mysql"/>
</bean>

  
 
  • 1
  • 2
  • 3
  • 4
  • 这种方式可以解决参数类型重复问题
  • 但是如果构造方法参数顺序发生变化后,这种方式又带来了耦合问题

依赖注入方式的选择

两种参数的注入方式,具体我们该如何选择呢?

  1. 强制依赖使用构造器进行,使用setter注入有概率不进行注入导致null对象出现

    强制依赖指对象在创建的过程中必须要注入指定的参数

  2. 可选依赖使用setter注入进行,灵活性强

    可选依赖指对象在创建过程中注入的参数可有可无

  3. Spring框架倡导使用构造器,第三方框架内部大多数采用构造器注入的形式进行数据初始化,相对严谨
  4. 如果有必要可以两者同时使用,使用构造器注入完成强制依赖的注入,使用setter注入完成可选依赖的注入
  5. 实际开发过程中还要根据实际情况分析,如果受控对象没有提供setter方法就必须使用构造器注入
  6. 自己开发的模块推荐使用setter注入

总结

  • setter注入

    • 简单数据类型

      <bean ...>
      	<property name="" value=""/>
      </bean>
      
            
           
      • 1
      • 2
      • 3
    • 引用数据类型

      <bean ...>
      	<property name="" ref=""/>
      </bean>
      
            
           
      • 1
      • 2
      • 3
  • 构造器注入

    • 简单数据类型

      <bean ...>
      	<constructor-arg name="" index="" type="" value=""/>
      </bean>
      
            
           
      • 1
      • 2
      • 3
    • 引用数据类型

      <bean ...>
      	<constructor-arg name="" index="" type="" ref=""/>
      </bean>
      
            
           
      • 1
      • 2
      • 3
  • 依赖注入的方式选择上

    • 建议使用setter注入
    • 第三方技术根据情况选择

文章来源: blog.csdn.net,作者:十八岁讨厌编程,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/zyb18507175502/article/details/125733449

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。