文章目录
- 🌴什么是依赖注入
- 🎄依赖注入的三种方法
- 🚩属性注⼊(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 {@Autowiredprivate 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() {}@Autowiredpublic 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;@Autowiredpublic void setStudentService(StudentService studentService) {this.studentService = studentService;}public void run() {System.out.println("StudentController启动");studentService.run();}}
🚩三种注⼊的优缺点
属性注⼊:
-
优点:
- 简洁,使⽤⽅便;
-
缺点:
-
只能⽤于IoC容器,如果是⾮IoC容器不可⽤,并且只有在使⽤的时候才会出现NPE(空指针异常)
-
不能注⼊⼀个Final修饰的属性
-
构造函数注⼊(Spring 4.X推荐):
- 优点:
-
可以注⼊final修饰的属性
-
注⼊的对象不会被修改
-
依赖对象在使⽤前⼀定会被完全初始化,因为依赖是在类的构造⽅法中执⾏的,⽽构造⽅法是在类加载阶段就会执⾏的⽅法.
-
通⽤性好,构造⽅法是JDK⽀持的,所以更换任何框架,他都是适⽤的
-
- 缺点:
- 注⼊多个对象时,代码会⽐较繁琐
Setter注⼊(Spring3.X推荐):
-
优点:
- ⽅便在类实例之后,重新对该对象进⾏配置或者注⼊
-
缺点:
-
不能注⼊⼀个Final修饰的属性
-
注⼊对象可能会被改变,因为setter⽅法可能会被多次调⽤,就有被修改的⻛险.
-
🌳@Autowired存在的问题
当同⼀类型存在多个bean时,在使⽤@Autowired就会存在问题
比如我们有以下bean。
BeanFiguation.java代码如下:
@Configuration
public class BeanFiguation {@Beanpublic Student student1() {Student student = new Student();student.setId(11);student.setName("遇事");student.setAge(11);return student;}@Beanpublic Student student2() {Student student = new Student();student.setId(22);student.setName("问春风乄");student.setAge(22);return student;}
}
StudentController.java代码如下:
@RestController
public class StudentController {@Autowiredprivate Student student;public void run() {System.out.println(student);}
}
当我们进行启动时:
报错的原因是,⾮唯⼀的 Bean 对象
🌲解决@Autowired存在的问题
为了解决上述问题,Spring提供了以下4种解决⽅案:
- bean对象名称与属性名相匹配
- @Primary
- @Qualifier
- @Resource
第一种:bean对象名称与属性名相匹配
第二种:使⽤@Primary注解:当存在多个相同类型的Bean注⼊时,加上@Primary注解,来确定默认的实现.
第三种:使⽤@Qualifier注解:指定当前要注⼊的bean对象。在@Qualifier的value属性中,指定注⼊的bean的名称。
- @Qualifier注解不能单独使⽤,必须配合@Autowired使⽤
第四种:使⽤@Resource注解:是按照bean的名称进⾏注⼊。通过name属性指定要注⼊的bean的名称。
🍃@Autowird与@Resource的区别
-
@Autowired是spring框架提供的注解,⽽@Resource是JDK提供的注解
-
@Autowired默认是按照类型注⼊,⽽@Resource是按照名称注⼊.相⽐于@Autowired来说,@Resource⽀持更多的参数设置,例如:name设置,根据名称获取Bean。
⭕总结
关于《【JavaEE进阶】 依赖注⼊DI详解》就讲解到这儿,感谢大家的支持,欢迎各位留言交流以及批评指正,如果文章对您有帮助或者觉得作者写的还不错可以点一下关注,点赞,收藏支持一下!