理解Spring中的依赖注入和控制反转
依赖注入(Dependency Injection)是一种面向对象编程的设计模式,用于解决对象之间的依赖关系。它的基本思想是将对象的创建和管理工作交给容器来完成,而不是在应用程序中手动创建和管理对象,从而达到松耦合、易维护、易测试的目的。依赖注入的实现原理是通过反射机制实现的。当一个对象需要依赖其他对象时,容器会通过反射机制查找和创建相应的对象,并将它们注入到需要依赖的对象中。这样,对象之间的依赖关系就由容器来维护,开发者只需要通过配置文件或注解等方式,告诉容器如何创建和注入对象。
在 Spring 框架中,依赖注入是通过 IoC(Inverse of Control,控制反转)实现的。IoC 容器在启动时,会扫描应用程序中的 Bean,并为每个 Bean 创建一个实例,并将它们存储在容器中。当其他 Bean 需要依赖这些 Bean 时,容器会自动将它们注入到需要依赖的 Bean 中。
具体来说,Spring 框架中的依赖注入主要有以下三种方式:
基于构造函数的依赖注入:通过构造函数来注入依赖项。
基于 Setter 方法的依赖注入:通过 Setter 方法来注入依赖项。
基于字段注入:通过直接将依赖项注入到类的字段中来实现。
那么什么是控制反转IoC呢?IoC 的基本思想是将程序中对象之间的依赖关系由程序员手动控制转变为由容器自动控制,即将对象的创建和管理工作交给容器来完成,而不是在应用程序中手动创建和管理对象。
依赖注入实际是通过反射机制实现的,反射机制实现依赖注入的具体步骤如下所示:
读取配置文件或者注解,获取依赖关系信息。
遍历依赖关系,通过反射机制获取依赖对象的类类型,然后使用 Class 类的 newInstance() 方法创建对象实例。
如果依赖对象有构造器参数,则通过递归调用实现构造器注入。
如果依赖对象有 setter 方法,则通过反射调用 setter 方法实现属性注入。
既然依赖注入本质是通过反射机制实现,那么什么是反射机制呢?反射机制是指在程序运行时动态获取类信息、访问或修改对象属性、调用对象方法等操作的一种机制。Java 反射机制提供了一组 API,使得程序能够在运行时获取并使用类的信息,而不需要在编译期间就确定。Java 反射机制提供了以下一些常用的 API:
Class 类:表示一个类的信息,可以获取类名、包名、父类、接口、构造器、属性、方法等信息。
Constructor 类:表示一个类的构造器信息,可以获取构造器的参数、修饰符、注解等信息。
Field 类:表示一个类的属性信息,可以获取属性名、类型、修饰符、注解等信息。
Method 类:表示一个类的方法信息,可以获取方法名、返回类型、参数、修饰符、注解等信息。
Modifier 类:提供了一组静态方法,可以判断一个类、方法或属性的修饰符,如 public、private、static、final 等。
Array 类:提供了一组静态方法,可以创建数组对象、获取数组长度、获取数组元素等信息。
下面是一段demo代码,通过实际代码来理解Java提供的反射机制的API如何使用。如下图所示,左边是定义的一个简单Person的class,右边是调用反射机制提供的API或者Person类的构造器,属性,对属性进行设置,调用Person类的方法等。在获取属性时,我们使用了 setAccessible(true) 方法,这是因为 name 和 age 属性都是私有的,需要通过反射机制打开访问权限才能修改它们的值。在调用方法时,我们使用了 invoke 方法来执行该方法。

可以看到通过反射机制,可以获取构造函数,设置属性值等,下面看看如何通过反射机制提供的API实现依赖注入。在下面的代码中,创建了UserService,UserService依赖UserDao。使用Class.forName()方法获取UserService类的Class对象,然后使用getConstructor()方法获取UserService类的构造函数,该构造函数需要一个UserDao类型的参数。接着,我们创建一个UserDao对象,然后通过newInstance()方法调用构造函数来创建UserService对象并注入依赖。另外,我们还可以使用getMethod()方法获取UserService类的setter方法,然后使用invoke()方法调用该方法来注入依赖。
public class UserService {private UserDao userDao;// 构造函数注入public UserService(UserDao userDao) {this.userDao = userDao;}// setter方法注入public void setUserDao(UserDao userDao) {this.userDao = userDao;}
}
public class UserDao {// ...
}
public class Main {public static void main(String[] args) throws Exception {// 通过反射机制创建UserService对象并注入依赖Class<?> userServiceClass = Class.forName("com.example.UserService");Constructor<?> userServiceConstructor = userServiceClass.getConstructor(UserDao.class);UserDao userDao = new UserDao();UserService userService = (UserService) userServiceConstructor.newInstance(userDao);// 或者通过setter方法注入依赖Method setUserDaoMethod = userServiceClass.getMethod("setUserDao", UserDao.class);userDao = new UserDao();setUserDaoMethod.invoke(userService, userDao);}
}以上是Spring使用Java的反射机制实现依赖注入的简单介绍。当然,Spring中的依赖注入还涉及到很多细节和实现方式,但是基本的原理就是通过反射机制动态地创建对象并注入依赖。总结而言,Spring实现依赖注入可以划分为4个步骤:
配置Bean
在Spring中,Bean的配置可以通过XML配置文件、注解或Java代码来实现。在配置中可以定义Bean的属性、依赖关系等信息,这部分是程序员编写,例如通过注解@Autowired等进行配置。
容器创建Bean
当Spring容器(容器是Spring框架的核心,它负责创建、管理和调用Bean)启动时,它会根据配置文件中的定义,通过Java的反射机制创建所有需要的Bean,并将它们存储在容器中。
注入依赖
在容器创建Bean的过程中,Spring会通过依赖注入的方式自动将Bean所需要的依赖注入到Bean中。这个过程可以通过构造器注入、setter注入或接口注入来实现。
构造器注入:使用Bean的构造器来注入依赖。在Bean的构造器中,我们可以通过参数来传递依赖对象。Spring会通过Java的反射机制,自动为构造器注入需要的依赖对象。
setter注入:使用Bean的setter方法来注入依赖。在Bean中,我们可以定义setter方法来设置依赖对象。Spring会通过Java的反射机制,自动调用Bean的setter方法,将需要的依赖对象注入到Bean中。
接口注入:使用接口来注入依赖。在Bean中,我们可以定义一个接口,并在接口中定义依赖注入的方法。Spring会通过Java的反射机制,自动实现这个接口,并将实现后的对象注入到Bean中。
总的来说,Spring实现依赖注入的核心就是将Bean的创建和依赖注入的过程交给了Spring容器来管理。Spring容器在创建Bean的过程中,通过Java的反射机制来自动完成Bean的依赖注入。这种方式可以大大减少代码的复杂度,提高代码的可读性和可维护性。
相关文章:
理解Spring中的依赖注入和控制反转
依赖注入(Dependency Injection)是一种面向对象编程的设计模式,用于解决对象之间的依赖关系。它的基本思想是将对象的创建和管理工作交给容器来完成,而不是在应用程序中手动创建和管理对象,从而达到松耦合、易维护、易…...
XXL-JOB
XXL-JOB介绍 XXL-JOB是一个轻量级分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线,开箱即用。 官网:https://www.xuxueli.com/xxl-job/ 文档:分布式任务调度…...
「牛客网C」初学者入门训练BC134,BC136
🐶博主主页:ᰔᩚ. 一怀明月ꦿ ❤️🔥专栏系列:线性代数,C初学者入门训练 🔥座右铭:“不要等到什么都没有了,才下定决心去做” 🚀🚀🚀大家觉不错…...
华为OD机试题【翻转单词顺序】用 C++ 进行编码 (2023.Q1)
最近更新的博客 华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为od机试,独家整理 已参加机试人员的实战技巧文章目录 最近更新的博客使用说明翻转单…...
4.Spring【Java面试第三季】
4.Spring【Java面试第三季】前言推荐4.Spring27_Aop的题目说明要求Spring的AOP顺序AOP常用注解面试题28_spring4下的aop测试案例业务类新建一个切面类MyAspect并为切面类新增两个注解:spring4springboot1.5.9pom测试类29_spring4下的aop测试结果aop正常顺序异常顺序…...
ZLibrary使用说明-Zlirbrary
ZLibrary使用说明如果您是一位书虫,那么ZLibrary是一个值得一试的网站。该网站提供了大量的免费电子书籍,涵盖了各种不同的主题和类别。下面是一些有关如何使用ZLibrary的详细说明:第1步:访问ZLibrary网站要使用ZLibraryÿ…...
TwinCAT3第三方伺服电机——汇川SV660N使用
目录 一、第三方伺服在TC3中配置和使用 二、xml文件拷贝 编辑 三、IO中扫描伺服 四、工程测试 五、汇川伺服参数设置说明 一、第三方伺服在TC3中配置和使用 在倍福控制系统中使用第三方伺服可以参见本人另一篇博客,有详细教程说明。本文仅仅对SV660N伺服设置…...
进制转换(二进制,八进制,十进制,十六进制)涵盖整数与小数部分,内容的图片全为手写【详细图解】
各种进制之间的相互转换1. 各进制表示数1.1 数码1.2 基数1.3 位权2. 十进制转换为其他进制2.1 整数部分2.2 小数部分3. 其他进制转换为十进制4. 二进制转换为八进制5. 二进制转换为十六进制6. 八进制转换为十六进制1. 各进制表示数 二进制:0,1逢二进一 八…...
谈谈XR关键技术及VR/AR/MR/XR关系
一、先别被VR/AR/MR/XR搞晕,说说区别虚拟现实(Virtual Reality,VR)、增强现实(Augmented Reality,AR)等业务以其三维化、自然交互、空间计算等完全不同于当前移动互联网的特性,被认为…...
acwing1562 微博转发(宽搜)
微博被称为中文版的 Twitter。 微博上的用户既可能有很多关注者,也可能关注很多其他用户。 因此,形成了一种基于这些关注关系的社交网络。 当用户在微博上发布帖子时,他/她的所有关注者都可以查看并转发他/她的帖子,然后这些人…...
如何使用Arsenal快速部署功能强大的Bug Bounty工具
关于Arsenal Arsenal是一个功能强大且使用简单的Shell脚本(Bash),该工具专为漏洞赏金猎人设计,在该工具的帮助下,我们可以轻松在自己环境中安装并部署目前社区中功能最为强大的网络侦查工具、漏洞扫描工具和其他安全研…...
(十)python网络爬虫(理论+实战)——正则表达式再讨论、常用正则表达式整理
系列文章目录 (1)python网络爬虫—快速入门(理论+实战)(一) (2)python网络爬虫—快速入门(理论+实战)(二) (3) python网络爬虫—快速入门(理论+实战)(三) (4)python网络爬虫—快速入门(理论+实战)(四) (5)...
MyBatis-Plus特性及插件整合
了解MyBatis-Plus 什么是MyBatis-Plus? mybatisPlus在mybatis的基础上继续针对CRUD操作进行优化,在原有的基础上提供了公共的接口BaseMapper,我们在创建接口Mapper时只需要继承这个接口即可调用MyBatisPlus已经提供好的方法,sql…...
应用篇|网络安全知识培训考试,答题小程序操作指引
网络安全知识培训考试,答题小程序操作指引关于全民防诈反诈宣传或者网络安全知识学习,如何进行组织一场微信线上答题考试?可以在小程序“护网专题信息安全知识竞答”,先创建一个学习单位/小组,再邀请成员加入单位/小组…...
官方不推荐@Autowired
1用lombok注解 2 构造器...
【牛客刷题专栏】0x0E:JZ6 从尾到头打印链表(C语言编程题)
前言 个人推荐在牛客网刷题(点击可以跳转),它登陆后会保存刷题记录进度,重新登录时写过的题目代码不会丢失。个人刷题练习系列专栏:个人CSDN牛客刷题专栏。 题目来自:牛客/题库 / 在线编程 / 剑指offer: 目录前言问题…...
Zeppelin安装
1、下载Zeppelin 下载地址:Download 2.解压 [rootguo147 install]# tar -zxvf zeppelin-0.10.0-bin-all.tgz -C ../soft/ //修改文件名 [rootguo147 soft]# mv zeppelin-0.10.0-bin-all/ zeppelin 3.配置 //进入conf 目录 [rootguo147 conf]# pwd /opt/soft/zepp…...
【蓝桥杯选拔赛真题38】python目标值判断 青少年组蓝桥杯python 选拔赛STEMA比赛真题解析
目录 python目标值判断 一、题目要求 1、编程实现 2、输入输出 二、解题思路...
Python jieba分词如何添加自定义词和去除不需要长尾词
Python jieba分词如何添加自定义词和去除不需要长尾词 作者:虚坏叔叔 博客:https://xuhss.com 早餐店不会开到晚上,想吃的人早就来了!😄 通过如下代码,读取一个txt的高频词汇: # 找到高频词汇t…...
云打包苹果证书生成、上架和应用截屏攻略
在使用apicloud或hbuilderx这些跨端的开发工具开发移动应用的时候,假如是打包ios应用,是需要生成苹果证书、证书profile文件,和对应用上架的。首先要普及一个概念,苹果的应用是无法像安卓那样挂在自己的服务器上下载直接安装就可以…...
铭豹扩展坞 USB转网口 突然无法识别解决方法
当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...
华为云AI开发平台ModelArts
华为云ModelArts:重塑AI开发流程的“智能引擎”与“创新加速器”! 在人工智能浪潮席卷全球的2025年,企业拥抱AI的意愿空前高涨,但技术门槛高、流程复杂、资源投入巨大的现实,却让许多创新构想止步于实验室。数据科学家…...
idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...
JavaScript 中的 ES|QL:利用 Apache Arrow 工具
作者:来自 Elastic Jeffrey Rengifo 学习如何将 ES|QL 与 JavaScript 的 Apache Arrow 客户端工具一起使用。 想获得 Elastic 认证吗?了解下一期 Elasticsearch Engineer 培训的时间吧! Elasticsearch 拥有众多新功能,助你为自己…...
.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...
智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql
智慧工地管理云平台系统,智慧工地全套源码,java版智慧工地源码,支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求,提供“平台网络终端”的整体解决方案,提供劳务管理、视频管理、智能监测、绿色施工、安全管…...
【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器
——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的一体化测试平台,覆盖应用全生命周期测试需求,主要提供五大核心能力: 测试类型检测目标关键指标功能体验基…...
YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...
[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...
