[Spring实战系列](7)Spring注入方式之构造器注入

简介: 版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/SunnyYoona/article/details/50630847 1. 构造器注入基于构造器的注入通过调用带参数的构造器来实现,每个参数代表着一个协作者。
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/SunnyYoona/article/details/50630847



1. 构造器注入


基于构造器的注入通过调用带参数的构造器来实现,每个参数代表着一个协作者。


1.1 最简单形式


我们以下面的Student实体类为例进行说明:

 
  
package com.sjf.bean;
 
/**
* 学生实体类
* @author sjf0115
*
*/
public class Student {
private String name;
private String company;
private int age;
private boolean sex;
public Student(String name, String company, int age, boolean sex) {
this.name = name;
this.company = company;
this.age = age;
this.sex = sex;
}
 
@Override
public String toString() {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("个性详细信息如下:" + "\n");
stringBuilder.append("name:" + name + "\n");
stringBuilder.append("company:" + company + "\n");
stringBuilder.append("age:" + age + "\n");
stringBuilder.append("sex:" + (sex ? "boy" : "girl"));
return stringBuilder.toString();
}
}

Student类有四个属性:name,company,age,sex。这四个属性是通过构造器注入来设置。重写Student的toString()方法来展示Student对象信息。

 
   
<?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 = "yoona" class = "com.sjf.bean.Student">
<constructor-arg value = "yoona"/>
<constructor-arg value = "Facebook"/>
<constructor-arg value = "24"/>
<constructor-arg value = "true"/>
</bean>
 
</beans>

运行结果:
 
    
name:yoona
company:Facebook
age:24
sex:true

1.2 根据type属性传值

bean中的constructor-arg元素用于通过构造器注入来设置属性。因为Student类中只有一个构造器,所以该代码没有任何问题。当有相同个数的构造器时,将会出现冲突。考虑如下:

我们为Student类提供了 两个构造器:
 
    
public Student(String name, String company) {
this.name = name;
this.company = company;
}
 
public Student(String name, int age) {
this.name = name;
this.age = age;
}
配置文件:
 
     
<bean id = "yoona" class = "com.sjf.bean.Student">
<constructor-arg value = "yoona"/>
<constructor-arg value = "24"/>
</bean>

那么现在你认为哪个构造器将被调用?按照我们的思维应该是第二个带String和int参数的构造器,真的吗?实际上Spring将调用第一个构造器。即使我们知道第一个参数是String,第二个参数是int,但是Spring将其都解析为String。
运行结果:
 
   
name:yoona
company:24

针对上面的这种情况,我们可以在构造器参数定义中使用type属性来显式的指定参数所对应的简单类型。现在如下配置,第二个构造器将被调用:
 
   
<bean id = "yoona" class = "com.sjf.bean.Student">
<constructor-arg type = "java.lang.String" value = "yoona"/>
<constructor-arg type = "int" value = "24"/>
</bean>
这样设置之后value="24"则是int类型,不会被认为是String,所以只能匹配  public Student ( String name , int age )  构造器。
运行结果:
 
   
name:yoona
age:24

1.3 根据index属性传值


通过使用index属性可以显式的指定构造器参数出现顺序。指定构造器参数索引是使用构造器IoC首选的方式。


那么现在考虑如下情况。我们在Student类中有如下的构造器

 
    
public Student( int age, String company) {
this.company = company;
this.age = age;
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}

进行如下配置:
 
   
<bean id = "yoona" class = "com.sjf.bean.Student">
<constructor-arg type = "java.lang.String" value = "yoona"/>
<constructor-arg type = "int" value = "24"/>
</bean>

那么现在你认为哪个构造器将被调用?第二个?但是实际上调用了第一个构造器。在调用构造器,配置文件中定义的参数顺序并没有先后之分。
运行结果:
 
    
company:yoona
age:24

要解决该问题,需要指定index属性,配置如下:
 
   
<bean id = "yoona" class = "com.sjf.bean.Student">
<constructor-arg index = "0" value = "yoona"/>
<constructor-arg index = "1" value = "24"/>
</bean>
这样设置之后,value="yoona" 必须对应构造器中的第一个参数,所以只能匹配  public Student ( String name , int age )  构造器。
运行结果:
 
   
name:yoona
age:24

1.4 根据name属性传值


其实还有一个得推荐的方式:根据name属性进行匹配。针对上面的构造器我们使用name属性进行配置如下:

 
  
<bean id = "yoona" class = "com.sjf.bean.Student">
<constructor-arg name = "name" value = "yoona"/>
<constructor-arg name = "age" value = "24"/>
</bean>
这样配置之后,value="yoona" 只能对应name属性,value="24"只能对应age属性。

运行结果:
 
   
name:yoona
age:24

1.5 通过构造器注入对象引用


我们为Student提供一个学校实体类:

 
   
package com.sjf.bean;
 
/**
* 学校实体类
* @author sjf0115
*
*/
public class School {
private String name;
private String location;
public School(String name, String location) {
this.name = name;
this.location = location;
}
 
@Override
public String toString() {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("name:" + name);
stringBuilder.append(" location:" + location);
return stringBuilder.toString();
}
}
我们使用构造器注入的方式School类进行配置:
 
   
<bean id = "xidian" class = "com.sjf.bean.School">
<constructor-arg index = "0" value = "西电"/>
<constructor-arg index = "1" value = "西安"/>
</bean>


 
   
package com.sjf.bean;
 
/**
* 学生实体类
* @author sjf0115
*
*/
public class Student {
private String name;
private School school;
private int age;
public Student(String name, School school, int age) {
this.name = name;
this.school = school;
this.age = age;
}
 
 
@Override
public String toString() {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("个人详细信息如下:" + "\n");
stringBuilder.append("name:" + name + "\n");
stringBuilder.append("age:" + age + "\n");
stringBuilder.append("school:" + school.toString());
return stringBuilder.toString();
}
}
为Student进行配置:

 
  
<bean id = "yoona" class = "com.sjf.bean.Student">
<constructor-arg name = "name" value = "yoona"/>
<constructor-arg name = "age" value = "24"/>
<constructor-arg name = "school" ref = "xidian"/>
</bean>
在这我们不能使用value属性为第二个构造参数赋值,因为School不是简单类型。取而代之的是,我们使用ref属性将ID为xidian的Bean引用传递给构造器。





目录
相关文章
|
12天前
|
Java 测试技术 程序员
为什么Spring不推荐@Autowired用于字段注入?
作为Java程序员,Spring框架在日常开发中使用频繁,其依赖注入机制带来了极大的便利。然而,尽管@Autowired注解简化了依赖注入,Spring官方却不推荐在字段上使用它。本文将探讨字段注入的现状及其存在的问题,如难以进行单元测试、违反单一职责原则及易引发NPE等,并介绍为何Spring推荐构造器注入,包括增强代码可读性和维护性、方便单元测试以及避免NPE等问题。通过示例代码展示如何将字段注入重构为构造器注入,提高代码质量。
|
2天前
|
缓存 NoSQL Java
Spring Boot与Redis:整合与实战
【10月更文挑战第15天】本文介绍了如何在Spring Boot项目中整合Redis,通过一个电商商品推荐系统的案例,详细展示了从添加依赖、配置连接信息到创建配置类的具体步骤。实战部分演示了如何利用Redis缓存提高系统响应速度,减少数据库访问压力,从而提升用户体验。
8 2
|
15天前
|
Java 数据库连接 Spring
【2021Spring编程实战笔记】Spring开发分享~(下)
【2021Spring编程实战笔记】Spring开发分享~(下)
22 1
|
16天前
|
缓存 Java Spring
源码解读:Spring如何解决构造器注入的循环依赖?
本文详细探讨了Spring框架中的循环依赖问题,包括构造器注入和字段注入两种情况,并重点分析了构造器注入循环依赖的解决方案。文章通过具体示例展示了循环依赖的错误信息及常见场景,提出了三种解决方法:重构代码、使用字段依赖注入以及使用`@Lazy`注解。其中,`@Lazy`注解通过延迟初始化和动态代理机制有效解决了循环依赖问题。作者建议优先使用`@Lazy`注解,并提供了详细的源码解析和调试截图,帮助读者深入理解其实现机制。
17 1
|
5天前
|
XML Java 数据格式
Spring IOC容器的深度解析及实战应用
【10月更文挑战第14天】在软件工程中,随着系统规模的扩大,对象间的依赖关系变得越来越复杂,这导致了系统的高耦合度,增加了开发和维护的难度。为解决这一问题,Michael Mattson在1996年提出了IOC(Inversion of Control,控制反转)理论,旨在降低对象间的耦合度,提高系统的灵活性和可维护性。Spring框架正是基于这一理论,通过IOC容器实现了对象间的依赖注入和生命周期管理。
17 0
|
15天前
|
XML Java 数据库连接
【2020Spring编程实战笔记】Spring开发分享~(上)
【2020Spring编程实战笔记】Spring开发分享~
40 0
|
2月前
|
JSON Java API
解码Spring Boot与JSON的完美融合:提升你的Web开发效率,实战技巧大公开!
【8月更文挑战第29天】Spring Boot作为Java开发的轻量级框架,通过`jackson`库提供了强大的JSON处理功能,简化了Web服务和数据交互的实现。本文通过代码示例介绍如何在Spring Boot中进行JSON序列化和反序列化操作,并展示了处理复杂JSON数据及创建RESTful API的方法,帮助开发者提高效率和应用性能。
103 0
|
2月前
|
缓存 Java 数据库连接
Spring Boot 资源文件属性配置,紧跟技术热点,为你的应用注入灵动活力!
【8月更文挑战第29天】在Spring Boot开发中,资源文件属性配置至关重要,它让开发者能灵活定制应用行为而不改动代码,极大提升了可维护性和扩展性。Spring Boot支持多种配置文件类型,如`application.properties`和`application.yml`,分别位于项目的resources目录下。`.properties`文件采用键值对形式,而`yml`文件则具有更清晰的层次结构,适合复杂配置。此外,Spring Boot还支持占位符引用和其他外部来源的属性值,便于不同环境下覆盖默认配置。通过合理配置,应用能快速适应各种环境与需求变化。
40 0
|
5月前
|
XML Java 程序员
Spring6框架中依赖注入的多种方式(推荐构造器注入)
依赖注入(DI)是一种过程,对象通过构造函数参数、工厂方法的参数或在对象实例构建后设置的属性来定义它们的依赖关系(即与其一起工作的其他对象)。
82 3
|
Java 测试技术 开发者
Spring构造器注入有多好?
Spring构造器注入有多好?
1076 0
Spring构造器注入有多好?