最近看到一个大佬写的代码,使用@Autowired依赖注入了一个类,但是这个类却只有一个有参构造,因而引起了我的深思,并决定自己实践一番,特写这篇文章,记录一下,不喜勿喷,余生还长,望与各位大佬互相学习、进步!
先说结论:
* 针对于@Autowired注解实例化bean选用构造器的几种情况: * * 一、没有在构造器上添加@Autowired注解 * (1)只有无参构造 -----使用无参构造 * (2)只有一个有参构造 -----使用的是有参构造,但是有参构造的形参类型必须要被spring管理,否则编译报错 * (3)有多个有参构造 -----编译报错 * (4)既有无参构造又有多个有参构造 -----使用无参构造 * * 二、在构造器上添加@Autowired注解 * (1)存在一个无参和一个有参构造,@Autowired加在无参构造 -----使用无参构造 * (2)存在一个无参和一个有参构造,@Autowired加在有参构造 -----使用的是有参构造 * (3)存在一个无参和一个有参构造,@Autowired加在两个上面 -----编译报错,提示注解只能加在某一个构造器上 * (4)存在一个无参和一个有参构造,@Autowired加在两个上面,但只有一个填写required = false -----运行报错 * (5)存在一个无参和一个有参构造,@Autowired加在两个上面,两个都填写required = false -----使用有参构造 * (6)存在一个无参和两个有参构造,@Autowired加在三个上面,三个都填写required = false -----使用形参个数多的构造器
首先我创建了四个类:
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Service;
@Service
@Data
@NoArgsConstructor
public class TempClass01 {
private String name;
private Integer age;
private String gender;
}
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Service;
@Service
@Data
@NoArgsConstructor
public class TempClass02 {
private String name;
private Integer age;
private String gender;
}
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
@Service
public class Teacher {
@Autowired
private Student student;
@PostConstruct
public void init() {
TempClass01 tempClass01 = student.getTempClass01();
System.out.println(tempClass01.toString());
System.out.println(tempClass01.getName());
}
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
@Data
public class Student {
private TempClass01 tempClass01;
private TempClass02 tempClass02;
@Autowired(required = false)
public Student() {
System.out.println("------------------使用的是无参构造");
}
@Autowired(required = false)
public Student(TempClass01 tempClass01) {
System.out.println("------------------使用的是一个参数的有参构造");
this.tempClass01 = tempClass01;
}
@Autowired(required = false)
public Student(TempClass01 tempClass01, TempClass02 tempClass02) {
System.out.println("------------------使用的是两个参数的有参构造");
this.tempClass01 = tempClass01;
this.tempClass02 = tempClass02;
}
}
说明:以上四个类展示的是全部代码,在验证上述结论,会根据情况注释部分代码!
一、没有在构造器上添加@Autowired注解
(1)student类只有无参构造
(2)只有一个有参构造
情况一:形参是基本数据类型:编译报错!
情况二:形参是引用数据类型:编译报错!
情况三:形参是自定义类,但是没有把类交给IOC容器管理:编译报错!
情况四:形参是自定义类,但是把类交给IOC容器管理:正常!
(3)有多个有参构造:编译异常!
(4)既存在无参构造,也存在多个有参构造
二、在构造器上添加@Autowired注解
(1)存在一个无参和一个有参构造,@Autowired加在无参构造
(2)存在一个无参和一个有参构造,@Autowired加在有参构造
(3)存在一个无参和一个有参构造,@Autowired加在两个上面:编译报错!
(4)存在一个无参和一个有参构造,@Autowired加在两个上面,但只有一个填写required = false:启动时报错!
(5)存在一个无参和一个有参构造,@Autowired加在两个上面,两个都填写required = false
(6)在一个无参和两个有参构造,@Autowired加在三个上面,三个都填写required = false
三、最后,好奇使用有参构造器,@Autowired注解注入的到底是什么,如果是对象,对象的属性值是什么,所以又实践了一番!下图是teacher类中的init方法执行结果!
文中应该还存在一些场景没有验证到,此时全靠小伙伴们自己动手实践啦!
* 总结: * 在不使用@Autowired注解的情况下:优先使用无参构造器,当无参构造器不存在且有参构造器唯一时,才使用有参构造器; * 在使用@Autowired注解的情况下:@Autowired注解唯一,则加在哪个构造器上就使用那个构造器; * 注解不唯一时,则必须加上required = false,此时,形参个数多的构造器优先使用。