👉 博客主页:准Java全栈开发工程师 👉 00年出生,即将进入职场闯荡,目标赚钱,可能会有人觉得我格局小、觉得俗,但不得不承认这个世界已经不再是以一条线来分割的平面,而是围绕财富旋转的球面,成为有钱人不是为了去掌控球体的转向,而是当有人恶意掌控时,努力保护好家人和自己。
依赖注入 - setter注入、构造器注入
- 一、依赖注入简介
- 二、注入方式的选择
- 三、setter注入 - 注入引用数据类型
- 1、定义所需dao层接口及其实现类,service接口及其实现类
- 1)BeanDao接口
- 2)BeanDaoImpl实现类
- 3)BeanService接口
- 4)BeanServiceImpl实现类,该类需要依赖注入BeanDao
- 2、applicationContext.xml文件中配置bean对象及完成依赖注入操作
- 3、测试代码
- 4、测试结果
- 四、setter注入 - 注入基本数据类型
- 1、定义所需dao层接口及其实现类
- 1)BeanDao接口
- 2)BeanDaoImpl实现类 - 定义了String类型的name和Integer类型的age及setter方法
- 2、在xml文件中配置bean
- 3、编写测试代码
- 4、测试结果
- 五、setter注入方式小结
- 六、构造器注入方式 - 注入引用数据类型
- 1、定义dao层接口及其实现类,service接口及其实现类
- 1)BeanDao接口
- 2)BeanDaoImpl实现类
- 3)BeanService接口
- 4)BeanServiceImpl实现类,该类需要依赖注入BeanDao
- 2、在配置文件中定义bean对象并依赖注入
- 3、编写测试代码
- 4、测试结果
- 七、构造器注入方式小结
- 八、构造器注入方式的缺点及改进方式
一、依赖注入简介
- 简单来说,依赖注入就是通过某种方式给属性赋值。
- 依赖注入有两种方式,一种是setter注入;另一种是构造器注入。
- 注入的数据类型有:基本数据类型和引用数据类型。
二、注入方式的选择
- 对于强制依赖关系,可以使用构造器注入方式,因为在创建对象时一定会调用到构造器方法;而setter注入方法有较低概率不进行注入。
- setter注入的灵活性强,对于可选的依赖关系,使用setter注入方式。
- 但Spring框架推荐使用构造器注入方式,因为该方式更为严谨,这也是Spring框架所追求的。
- 当然也可以同时进行构造器注入和setter方法注入。
- 在自己开发过程中,一般情况下更推荐使用setter注入方式。原因见下文对setter注入和构造器注入的详细介绍。
三、setter注入 - 注入引用数据类型
1、定义所需dao层接口及其实现类,service接口及其实现类
1)BeanDao接口
public interface BeanDao {
public void save();
}
2)BeanDaoImpl实现类
public class BeanDaoImpl implements BeanDao {
public void save() {
System.out.println("beanDao save...");
}
}
3)BeanService接口
public interface BeanService {
public void save();
}
4)BeanServiceImpl实现类,该类需要依赖注入BeanDao
public class BeanServiceImpl implements BeanService {
private BeanDao beanDao;
public void setBeanDao(BeanDao beanDao) {
this.beanDao = beanDao;
}
public void save() {
System.out.println(" bean service save...");
beanDao.save();
}
}
2、applicationContext.xml文件中配置bean对象及完成依赖注入操作
<bean id="beanDao" class="dao.impl.BeanDaoImpl"/>
<bean id="beanService" class="service.impl.BeanServiceImpl">
<property name="beanDao" ref="beanDao" />
</bean>
- 使用“property”标签来实现依赖注入操作。
- 其中“name”属性指"BeanServiceImpl"类中指定的属性名
- “ref”属性指定前面创建的bean对象的id属性值“beanDao"。
3、测试代码
public class App {
public static void main(String[] args) {
// 加载配置文件,获得上下文对象
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
BeanService beanService = (BeanService) context.getBean("beanService");
beanService.save();
}
}
4、测试结果
bean service save...
beanDao save...
四、setter注入 - 注入基本数据类型
1、定义所需dao层接口及其实现类
1)BeanDao接口
public interface BeanDao {
public void save();
}
2)BeanDaoImpl实现类 - 定义了String类型的name和Integer类型的age及setter方法
public class BeanDaoImpl implements BeanDao {
private String name;
private Integer age;
public void setName(String name) {
this.name = name;
}
public void setAge(Integer age) {
this.age = age;
}
public void save() {
System.out.println("beanDao save...");
System.out.println("name : " + name + " , age : " + age);
}
}
2、在xml文件中配置bean
<bean id="beanDao" class="dao.impl.BeanDaoImpl">
<property name="name" value="qdxorigin"/>
<property name="age" value="22"/>
</bean>
- 对于引用数据类型,需要使用“ref”属性指定bean对象的id属性值。
- 而对于基本数据类型,只需要通过“value”属性直接赋值即可。
3、编写测试代码
public class App {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
BeanDao beanDao = (BeanDao) context.getBean("beanDao");
beanDao.save();
}
}
4、测试结果
beanDao save...
name : qdxorigin , age : 22
注入信息能够正确输出。
五、setter注入方式小结
- 无论是注入基本数据类型还是引用数据类型,在定义了属性之后,都需要为其定义相应的setter方法。
- 在创建bean对象时,均是通过使用”property“标签来实现注入。
- 引用数据类型使用”ref“属性赋值;基本数据类型使用”value“属性赋值。
六、构造器注入方式 - 注入引用数据类型
1、定义dao层接口及其实现类,service接口及其实现类
1)BeanDao接口
public interface BeanDao {
public void save();
}
2)BeanDaoImpl实现类
public class BeanDaoImpl implements BeanDao {
public void save() {
System.out.println("beanDao save...");
}
}
3)BeanService接口
public interface BeanService {
public void save();
}
4)BeanServiceImpl实现类,该类需要依赖注入BeanDao
public class BeanServiceImpl implements BeanService {
private BeanDao beanDao;
public BeanServiceImpl(BeanDao beanDao) {
this.beanDao = beanDao;
}
public void save() {
System.out.println("bean service save...");
beanDao.save();
}
}
- 代码和setter注入非常相似,只是将setter方法改为了构造器方法。
2、在配置文件中定义bean对象并依赖注入
<bean id="beanDao" class="dao.impl.BeanDaoImpl"/>
<bean id="beanService" class="service.impl.BeanServiceImpl">
<constructor-arg name="beanDao" ref="beanDao"/>
</bean>
- 细心的小伙伴已经发现了,在定义bean对象时,只是将”property“标签换成了”constructor-arg“标签,其他所有的内容都是一样的。
- ”name“属性和”ref“属性的作用也是一样的。
3、编写测试代码
public class App {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
BeanService beanService = (BeanService) context.getBean("beanService");
beanService.save();
}
}
4、测试结果
bean service save...
beanDao save...
七、构造器注入方式小结
- 其实setter注入和构造器注入两种方式的实现代码是极其相似的,只有小部分的差别。
- 对于基本数据类型构造器注入方式的相关测试代码可以参考”setter注入 - 注入基本数据类型“相关内容,只需要把”BeanDaoImpl"类中的setter方法改为构造器方法,在xml文件注入时将“property"标签改为”constructor-arg“标签即可。
八、构造器注入方式的缺点及改进方式
- 构造器注入方法使用的”constructor-arg“标签中的“name”属性,该属性值指定的是构造器方法中的形参名,并不是类中定义的属性名,虽然一般情况下我们会将这两个命名保持一致。这样就导致如果我们修改了构造器形参名,也需要去修改”name“属性的值,不符合低耦合的特性。
为了解决上述问题,提出了可以使用”type“属性来解决参数名耦合高的问题。
<constructor-arg type="dao.BeanDao" ref="beanDao"/>
在构造器注入时,不使用”name“属性指定具体的名字,而是改用”type"属性指定类型,通过类型匹配来完成赋值。
虽然该方式解决了参数名问题,但是如果构造器方法的形参列表中有多个相同类型的参数呢?这时应该如何完成赋值呢?谁赋值给谁又有了新的问题。
- 使用“type”属性解决了参数名耦合问题,又出现了多个相同类型的参数赋值问题。
为了解决这个问题,又提出了使用“index”属性。
<constructor-arg index="0" ref="beanDao"/>
干脆直接使用“index”属性指定下标来进行赋值,这种方式虽然解决了相同类型参数的赋值问题,但是如果构造方法的形参列表中的参数顺序改变了呢?是不是又得来修改“index”属性的值呢?
所以,这也是为什么在“注入方式的选择”内容中,推荐使用setter方式注入的原因。
👉 以上就是文章的全部内容啦,诸佬如果有任何建议都可以提哦。