0
点赞
收藏
分享

微信扫一扫

[Spring Framework]DI依赖注入①


文章目录

  • ​​引入​​
  • ​​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;
}
}

  • 配置中使用property标签ref属性注入引用类型对象

<bean id="bookService" class="impl.BookServiceImpl">
<property name="bookDao" ref="bookDao"/>
</bean>

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

简单数据类型

简单数据类型与引用数据类型差不多,区别在于配置的时候不再使用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);
}
}

步骤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>

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

结果:

[Spring Framework]DI依赖注入①_xml

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

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

这样的话,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();
}
}

步骤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>

说明:

标签中

  • 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);
}
}

步骤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>

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

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

[Spring Framework]DI依赖注入①_java_02

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

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

优化方案一

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

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

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

优化方案二

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

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

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

依赖注入方式的选择

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

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

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

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

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

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

总结

  • setter注入
  • 简单数据类型

<bean ...>
<property name="" value=""/>
</bean>

  • 引用数据类型

<bean ...>
<property name="" ref=""/>
</bean>

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

<bean ...>
<constructor-arg name="" index="" type="" value=""/>
</bean>

  • 引用数据类型

<bean ...>
<constructor-arg name="" index="" type="" ref=""/>
</bean>

  • 依赖注入的方式选择上
  • 建议使用setter注入
  • 第三方技术根据情况选择


举报

相关推荐

0 条评论