【Java EE】依赖注入DI详解

news/2024/9/23 20:14:44/

文章目录

  • 🌴什么是依赖注入
  • 🍀依赖注入的三种方法
    • 🌸属性注入(Field Injection)
    • 🌸构造方法注入
    • 🌸Setter注入
    • 🌸三种注入优缺点分析
  • 🌳@Autowired存在的问题
  • 🌲解决@Autowired对应多个对象问题
  • 🍃@Autowird与@Resource的区别
  • ⭕总结

🌴什么是依赖注入

依赖注⼊是⼀个过程,是指IoC容器在创建Bean时, 去提供运⾏时所依赖的资源,⽽资源指的就是对象.

简单来说, 就是把对象取出来放到某个类的属性中

在⼀些⽂章中, 依赖注⼊也被称之为 “对象注⼊”, “属性装配”, 具体含义需要结合⽂章的上下⽂来理解

🍀依赖注入的三种方法

关于依赖注⼊, Spring也给我们提供了三种⽅式:

  1. 属性注⼊(Field Injection)
  2. 构造⽅法注⼊(Constructor Injection)
  3. 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修饰的属性

构造函数注入

  • 优点:
    – 可以注⼊final修饰的属性
    – 注⼊的对象不会被修改
    – 依赖对象在使⽤前⼀定会被完全初始化,因为依赖是在类的构造⽅法中执⾏的,⽽构造⽅法
    是在类加载阶段就会执⾏的⽅法.
    – 通⽤性好, 构造⽅法是JDK⽀持的, 所以更换任何框架,他都是适⽤的

  • 缺点:
    – 注⼊多个对象时, 代码会⽐较繁琐

Setter注入

  • 优点: ⽅便在类实例之后, 重新对该对象进⾏配置或者注⼊
  • 缺点:
    – 不能注⼊⼀个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注解,来确定默认的实现.

@Component
public class BeanConfig {@Primary //指定该bean为默认bean的实现@Bean("u1")public User user1(){User user = new User();user.setName("zhangsan");user.setAge(18);return user;}@Beanpublic 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名称@Autowiredprivate 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。

⭕总结

感谢大家的阅读,希望得到大家的批评指正,和大家一起进步,与君共勉!


http://www.ppmy.cn/news/1424807.html

相关文章

2024面试软件测试,常见的面试题(上)

一、综合素质 1、自我介绍 面试官您好,我叫XXX,一直从事车载软件测试,负责最多的是中控方面。 以下是我的一些优势: 车载的测试流程我是熟练掌握的,且能够独立编写测试用例。 平时BUG提交会使用到Jira,类似…

虚拟机磁盘剩余空间不足

VMware 弹出提示: 对文件“E:\Virtual Machine\CentOS 7 1810 的克隆 (2)\CentOS 7 1810-cl1.vmdk”的操作失败。 如果该文件位于远程文件系统上,请确保网络连接以及该磁盘所在的服务器正常工作。如果该文件位于可移动介质中,请重新连接该介…

javaagent使用

Java Agent是什么? Java Agent是Java平台提供的一个强大工具,它可以在运行时修改或增强Java应用程序的行为。是在JDK1.5以后引入的,它能够在不影响正常编译的情况下修改字节码,相当于是在main方法执行之前的拦截器,也叫…

android 修改kernel编译版本信息

1,android版本: 在android/build/core/version_defaults.mk中红色部分 ifeq "" "$(BUILD_NUMBER)" # BUILD_NUMBER should be set to the source control value that # represents the current state of the source code. E.g…

【数学建模】最优旅游城市的选择问题:层次分析模型(含MATLAB代码)

层次分析法(The analytic hierarachy process,简称AHP)是一种常用的决策分析方法,其基本思路是将复杂问题分解为多个组成部分,然后对这些部分进行逐一评估和比较,最后得出最优解决方案。(例如&a…

Git常见命令行操作和IDEA图形化界面操作

设置Git用户名和标签 在安装完Git以后需要设置用户和签名,至于为什么要设置用户签名可以看一下这篇文章【学了就忘】Git基础 — 11.配置Git用户签名说明 - 简书 (jianshu.com) 基本语法: git config --global user.name 用户名 git config --global u…

flutter书架形式格口的动态创建(行、列数,是否全选的配置)

根据传入的行列数创建不同格口数量的书架 左图:5行3列、右图:3行3列 代码 import package:jade/bean/experienceStation/ExpCellSpecsBean.dart; import package:jade/configs/PathConfig.dart; import package:jade/utils/DialogUtils.dart; import p…

【开源】使用Python+Flask+Mysql快速开发一个用户增删改查系统

项目演示 项目本身很简单,增删改查是几乎所有系统的骨架。正所谓万丈高楼平地起,学会了增删改查,航母就指日可待了:),光速入门,直接看演示图: 项目地址 https://github.com/mudf…