文章目录
- 🌴什么是依赖注入
- 🍀依赖注入的三种方法
- 🌸属性注入(Field Injection)
- 🌸构造方法注入
- 🌸Setter注入
- 🌸三种注入优缺点分析
- 🌳@Autowired存在的问题
- 🌲解决@Autowired对应多个对象问题
- 🍃@Autowird与@Resource的区别
- ⭕总结
🌴什么是依赖注入
依赖注⼊是⼀个过程,是指IoC容器在创建Bean时, 去提供运⾏时所依赖的资源,⽽资源指的就是对象.
简单来说, 就是把对象取出来放到某个类的属性中
在⼀些⽂章中, 依赖注⼊也被称之为 “对象注⼊”, “属性装配”, 具体含义需要结合⽂章的上下⽂来理解
🍀依赖注入的三种方法
关于依赖注⼊, Spring也给我们提供了三种⽅式:
- 属性注⼊(Field Injection)
- 构造⽅法注⼊(Constructor Injection)
- Setter 注⼊(Setter Injection)
🌸属性注入(Field Injection)
属性注⼊是使⽤ @Autowired 实现的。
比如我们将StudentService类注⼊到StudentController类中.
StudentService.java代码如下:
@Service
public class StudentService {
public void run() {
System.out.println("StudentService启动");
}
}
StudentController.java代码如下:
@RestController
public class StudentController {
@Autowired
private StudentService studentService;
public void run() {
System.out.println("StudentController启动");
studentService.run();
}
}
获取StudentController中的run方法
@SpringBootApplication
public class SpringMvcApplication {
public static void main(String[] args) {
//获取spring上下文
ApplicationContext context = SpringApplication.run(SpringMvcApplication.class, args);
//从spring中获取对象
StudentController studentController = context.getBean("studentController",StudentController.class);
//使用spring对象
studentController.run();
}
}
🌸构造方法注入
构造⽅法注⼊是在类的构造⽅法中实现注⼊,如下代码所示:
@RestController
public class StudentController {
private StudentService studentService;
public StudentController() {
}
@Autowired
public StudentController(StudentService studentService) {
this.studentService = studentService;
}
public void run() {
System.out.println("StudentController启动");
studentService.run();
}
}
注意事项:
- 如果类只有⼀个构造⽅法,那么@Autowired注解可以省略;如果类中有多个构造⽅法,那么需要添加上@Autowired来明确指定到底使⽤哪个构造⽅法
🌸Setter注入
Setter注入和属性的Setter⽅法实现类似,只不过在设置set⽅法的时候需要加上@Autowired注解
@RestController
public class StudentController {
private StudentService studentService;
@Autowired
public void setStudentService(StudentService studentService) {
this.studentService = studentService;
}
public void run() {
System.out.println("StudentController启动");
studentService.run();
}
}
🌸三种注入优缺点分析
属性注⼊:
- 优点: 简洁,使⽤⽅便;
- 缺点:
– 只能⽤于 IoC 容器,如果是⾮ IoC 容器不可⽤,并且只有在使⽤的时候才会出现 NPE(空指
针异常)
– 不能注⼊⼀个Final修饰的属性
构造函数注入
-
优点:
– 可以注⼊final修饰的属性
– 注⼊的对象不会被修改
– 依赖对象在使⽤前⼀定会被完全初始化,因为依赖是在类的构造⽅法中执⾏的,⽽构造⽅法
是在类加载阶段就会执⾏的⽅法.
– 通⽤性好, 构造⽅法是JDK⽀持的, 所以更换任何框架,他都是适⽤的 -
缺点:
– 注⼊多个对象时, 代码会⽐较繁琐
Setter注入
- 优点: ⽅便在类实例之后, 重新对该对象进⾏配置或者注⼊
- 缺点:
– 不能注⼊⼀个Final修饰的属性
– 注⼊对象可能会被改变, 因为setter⽅法可能会被多次调⽤, 就有被修改的⻛险
🌳@Autowired存在的问题
当同⼀类型存在多个bean时,在使⽤@Autowired就会存在问题
比如我们有以下bean。
BeanFiguation.java代码如下:
@Configuration
public class BeanFiguation {
@Bean
public Student student1() {
Student student = new Student();
student.setId(11);
student.setName("山高路远");
student.setAge(11);
return student;
}
@Bean
public Student student2() {
Student student = new Student();
student.setId(22);
student.setName("与君共勉");
student.setAge(22);
return student;
}
}
StudentController.java代码如下:
@RestController
public class StudentController {
@Autowired
private Student student;
public void run() {
System.out.println(student);
}
}
当我们进行启动时:
报错的原因是,⾮唯⼀的 Bean 对象
🌲解决@Autowired对应多个对象问题
为了解决上述问题,Spring提供了以下4种解决⽅案:
- bean对象名称与属性名相匹配
- @Primary
- @Qualifier
- @Resource
第一种:bean对象名称与属性名相匹配
第二种:使⽤@Primary注解:当存在多个相同类型的Bean注⼊时,加上@Primary注解,来确定默认的实现.
@Component
public class BeanConfig {
@Primary //指定该bean为默认bean的实现
@Bean("u1")
public User user1(){
User user = new User();
user.setName("zhangsan");
user.setAge(18);
return user;
}
@Bean
public User user2() {
User user = new User();
user.setName("lisi");
user.setAge(19);
return user;
}
}
第三种:使⽤@Qualifier注解:指定当前要注⼊的bean对象。在@Qualifier的value属性中,指定注⼊的bean的名称。
@Qualifier注解不能单独使⽤,必须配合@Autowired使⽤
@Controller
public class UserController {
@Qualifier("user2") //指定bean名称
@Autowired
private User user;
public void sayHi(){
System.out.println("hi,UserController...");
System.out.println(user);
}
}
第四种:使⽤@Resource注解:是按照bean的名称进⾏注⼊。通过name属性指定要注⼊的bean的名称。
@Controller
public class UserController {
@Resource(name = "user2")
private User user;
public void sayHi(){
System.out.println("hi,UserController...");
System.out.println(user);
}
}
🍃@Autowird与@Resource的区别
- @Autowired 是spring框架提供的注解,⽽@Resource是JDK提供的注解
- @Autowired 默认是按照类型注⼊,⽽@Resource是按照名称注⼊. 相⽐于 @Autowired 来说,@Resource ⽀持更多的参数设置,例如 name 设置,根据名称获取 Bean。
⭕总结
感谢大家的阅读,希望得到大家的批评指正,和大家一起进步,与君共勉!