Spring中的 DI 原理及源码解析

Spring中的DI的实现原理 缘起 上一篇中我们讲述了IOC容器的实现原理,我们知道IOC容器实际上就是把我们的Bean封装成一个BeanDefinition然后放入到一个map中,那么本篇主要讲述我们如何使用这个Bean,也就是所谓的依赖注入(DI)。 DI的实现原理 我们还是写这样一个简单的main方法来测试 getBean方法最终会调用AbstractBeanFactory类的getBean方法 看doGetBean... 阅读详情

前言

  Spring是一个强大的应用程序开发框架,它为企业应用程序提供了许多好处。其中一个主要特性就是IoC(控制反转)和DI(依赖注入)。本文将重点介绍Spring中的DI原理以及相关源码解析。

DI的定义

  依赖注入(Dependency Injection),简称DI,是指向对象实例的变量(即所依赖的对象)在程序运行过程中动态地被注入到对象中去。核心思想是:在程序运行时通过信息反转将某些依赖关系交给专门的容器去管理,在需要调用的时候由容器来主动地注入其依赖对象。

  Spring中的DI是将这个原理应用到实际编程中的一种方法。在Spring中,将会有一个容器(ApplicationContext)来负责所有对象的创建、初始化、销毁等操作,并且提供依赖注入机制,将所有需要的依赖对应的Bean交给需要使用的Bean进行依赖注入。

DI的实现原理

  Spring中的DI实现主要分为两种方式:构造函数注入和Setter方法注入。这两种方式都是通过Java反射机制实现的。

构造函数注入

  构造函数注入是指在创建对象的时候,通过构造函数传入需要注入的对象。要实现构造函数注入,在Bean类中需要提供一个构造函数,并且构造函数的参数类型需要与所需注入的对象相对应。

  例如,有一个需要依赖注入UserService的UserDao:

public class UserDaoImpl implements UserDao {
    private UserService userService;

    public UserDaoImpl(UserService userService) {
        this.userService = userService;
    }
}

  在ApplicationContext中,需要配置UserService和UserDao的Bean定义,然后通过构造函数将UserService实例传递给UserDao:

<bean id="userService" class="com.example.UserService"/>
<bean id="userDao" class="com.example.UserDaoImpl">
    <constructor-arg ref="userService"/>
</bean>

Setter方法注入

  Setter方法注入是指在Bean实例化后,通过setter方法动态地设置需要注入的对象。要实现Setter方法注入,在Bean类中需要提供setter方法,方法名需要与需要注入的属性名称相同。

  例如,有一个需要依赖注入UserService的UserDao:

public class UserDaoImpl implements UserDao {
    private UserService userService;

    // setter method for userService
    public void setUserService(UserService userService) {
        this.userService = userService;
    }
}

  在ApplicationContext中,需要配置UserService和UserDao的Bean定义,然后通过setter方法将UserService实例注入到UserDao:

<bean id="userService" class="com.example.UserService"/>
<bean id="userDao" class="com.example.UserDaoImpl">
    <property name="userService" ref="userService"/>
</bean>

DI源码解析

  Spring中的DI是通过BeanFactory和ApplicationContext两个接口实现的。在这两个接口中,主要涉及到了BeanDefinition和BeanWrapper等关键类。

BeanDefinition

  BeanDefinition是用来描述一个Bean实例在容器中的属性和行为的信息。在使用ApplicationContext加载配置文件时,会通过BeanDefinition将所有Bean的定义信息都保存在内存中。

  例如,在XML配置文件中定义UserService的Bean:

<bean id="userService" class="com.example.UserService"/>

  在内存中,会将这个Bean的信息保存在BeanDefinition中:

public class BeanDefinition {
    private String beanClassName; // 类全名
    private List<PropertyValue> propertyValues; // 属性值
    ...
}
BeanWrapper

  BeanWrapper是Spring中一个重要的类,它负责封装Bean的实例对象,并提供对Bean实例属性的读取和修改操作。在DI过程中,就是通过BeanWrapper来创建并初始化Bean实例、设置依赖关系等。

  例如,在ApplicationContext中加载UserService和UserDao的Bean:

<bean id="userService" class="com.example.UserService"/>
<bean id="userDao" class="com.example.UserDaoImpl">
    <property name="userService" ref="userService"/>
</bean>

  在创建UserDao实例时,会创建一个BeanWrapper对象,并调用它的setPropertyValues()方法来设置依赖关系:

GenericBeanDefinition bd = (GenericBeanDefinition) beanFactory.getBeanDefinition("userDao");
Object instance = beanFactory.createBean(bd);
BeanWrapper bw = new BeanWrapperImpl(instance);
bw.setPropertyValues(bd.getPropertyValues());
总结

  DI是Spring框架中非常重要的一个特性,通过使用依赖注入可以大大降低程序之间的耦合度,增加了程序的灵活性和可扩展性。本文对DI的实现原理进行了详细介绍,并分析了源码实现过程。

  在使用Spring框架时,熟悉DI的原理和实现方式对我们更好地理解框架的机制和使用方法有非常重要的作用。

spring源码解析专栏导航 目录 如何搭建Spring源码的阅读环境 Spring的整体架构介绍 Spring是如何读取xml中的bean配置并加入到IOC容器中的 阅读详情

相关推荐

深入剖析Spring依赖注入原理——从源码理解DI核心机制

Spring 允许将@Autowired与其他元注解组合,创建语义更丰富的自定义注解:@Autowired然后可在代码中使用:Spring 会递归解析元注解,识别出其包含@Autowired,从而正常触发注入。此外,对泛型的支持也十分完善。例如:@Autowired@Autowired支持延迟获取、流式遍历等高级操作:在Spring框架的底层实现中,是一个核心抽象概念,它承载了每一个Bean在容器中的完整元数据信息。

weixin_30995917的博客 1152

Spring(DI)

DI(Dependency Injection)即依赖注入,对象之间的依赖由容器在运行期决定,即容器动态的将某个依赖注入到对象自重 基于XML配置注入依赖 有参构造函数注入依赖 bean类实现有参构造函数 public class Student { private Integer id; private String name; /** * 有参构造函数 */ public Student(Integer id, String name) {

xasasaa的博客 1433

Spring框架外文文献、论文参考与Java源码深度解析

优势说明消除版本冲突所有starter共享同一版本基线简化依赖声明开发者只需关注“要什么”,而非“哪个版本”易于升级升级Spring Boot版本即同步更新所有子组件社区标准化形成统一的技术选型规范此外,Spring Boot还提供了与自动配置配合,实现“按需激活”。例如,仅当引入时才会触发,保证无冗余Bean加载。构建自定义Starter是高级开发者常见的需求,适用于封装公司内部中间件、通用工具包或特定业务模板。

weixin_28787801的博客 1166

【Spring框架】Spring中的DI介绍

Spring中的DI介绍 DI(Dependency Injection),即“依赖注入”,组件之间依赖关系由容器在运行期决定,即容器动态的将某个依赖关系注入到组件当中。它是是 Spring 框架核心IOC技术的具体实现。 依赖注入是控制反转最常用的方式,通过控制反转可以减低计算机代码之间的耦合度。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。 DI理解的关键点“谁依赖谁,为什么需要依赖” 谁依赖谁:应用程序依赖IOC容器

Sampson_S的博客 5976

【Cadence】stb仿真和ac仿真——以一个简单的全差分反相放大器仿真为例

最近在补一些仿真方法学的问题,以及一些一直以来都有点模糊的概念,简单记录一下。搭建一个以两个CMOS反相器构成的全差分放大器(28nm工艺,PMOS和NMOS尺寸一致)激励的设置方便共模和差模仿真用同一个TB(这里有一个问题:这个放大器需要在开环下仿真还是闭环下?哪些放大器应用在开环,哪些闭环?这种应用场景不同会导致需要仿真得到开环还是闭环增益,或者环路增益?(我知道放大器在设计的时候肯定都是闭环应用的多,但是什么时候没必要闭环应用?光验证ac和stb仿真是否一样的话有必要有回路吗?

weixin_44951108的博客 5万+

ros2 humble cartographer 2D激光雷达建图

Cartographer是一个支持多平台和传感器配置的SLAM的系统。 本文主要讲述在ros2 humble系统上cartographer的安装方法,以及如何配置参数实现自己的ros2 bag包的离线建图。

weixin_43087302的博客 6937

Spring 之 DI 详解

概念 DI(Dependency Injection)依赖注入:依赖注入是指在程序运行期间,由外部容器动态地将依赖对象注入到组件中如:一般,通过构造函数注入、Setter注入、注解注入。 Setter注入与注解注入类似,区别在于:Setter 注入是通过 Set 方法对属性进行赋值,而注解注入是通过反射为属性赋值。 时机 当 Spring IOC 容器完成了 Bean 定义资源的定位、载入、解析和注册以后,IOC 容器中已经管理类 BeanDefinition 的相关数据,但是此时 IOC 容器还没有对所管

岁月安然 3018

JavaFX - 动画

JavaFX 动画

思你日度难眠 1601

Spring DI详解

1.IOC(DI)-控制反转(依赖注入) 所谓的IOC称之为控制反转,简单来说就是将对象 的创建的权力及对象的生命周期的管理过程交由Spring框架来处理,从此在开发过程中不在需要关注对象的创建和生命周期的管理,而是在需要的时候由Spring框架提供,这个由Spring框架管理对象创建和生命周期的机制称之为控制反转。而在创建对象的过程中Spring可以依据配置对象的属性进行设置,这个过程称之为依...

qq_42603060的博客 1万+

深入浅出卡尔曼滤波器算法

深入浅出讲解卡尔曼滤波器的工作原理及其公式推导,讨论卡尔曼滤波器的核心公式所代表的意义及个人的理解。

m0_37835056的博客 1364

微信图片.dat文件解密实战:用Python一键转PNG(附完整代码)

本文详细介绍了如何通过Python解密微信图片.dat文件并转换为PNG格式的完整教程。文章深入解析了微信.dat文件的异或加密原理,提供了自动检测密钥的Python脚本,并分享了批量解密和性能优化的实用技巧,帮助用户轻松恢复和整理微信聊天图片。

weixin_29096377的博客 463

Spring DI简介及依赖注入方式和依赖注入类型

Spring DI简介及依赖注入方式和依赖注入类型

qq_53317005的博客 6441

嵌入式SDIO 总线面试题及参考答案

SDIO 的 4 位总线模式是一种提高数据传输效率的工作模式。在传统的 1 位总线模式下,数据只能通过一根数据线(DAT0)进行传输,这限制了数据传输的带宽和速度。而在 4 位总线模式下,DAT0 - DAT3 这 4 根数据线同时用于数据传输,相当于在同一时间内可以传输 4 倍于 1 位模式的数据量,从而显著提高了数据传输的带宽和速度。要通过 CMD6 命令将 SDIO 总线从当前模式切换到 4 位总线模式,需要遵循以下步骤:第一步,主设备需要确保 SDIO 卡支持 4 位总线模式。

大模型大数据攻城狮的专栏 1714

J2EE-026 Spring容器源码解析(一)构建后置处理器

Spring容器源码解析DI和IOCIOC(控制反转)提出问题源码梳理`registerAnnotationConfigProcessors`类关键代码:构建工厂`registerAnnotationConfigProcessors`类关键代码:判断图解![在这里插入图片描述](https://img-blog.csdnimg.cn/2021051023052261.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,te

qq_35059264的博客 477

IEC 61400-1:2019 附录 C 湍流模型全面解读

IEC 61400-1:2019 附录 C 全面解读

weixin_46713695的博客 470

ARM CoreLink 系列 5.1.1 -- CI-700 System Address Map 】

所有的CHI 命令都包含一个 Source ID 和 Target ID, 其中 Source ID 可以来自于 RN Node, Target ID 可以来自于HN node或者其他 SN node. 其中 Target ID 是通过 SAM解析传入的地址得到的。对于 CI-700中的所有 RN Node 中的 SAM 多会进行配置,因为RN Node 访问的是整个地址空间,不同的地址空间会有不同的属性(I/O, DRAM),所以会对RN SAM 配置多个不同属性的区域。

CodingCos的博客 770

Spring从入门到源码解析——博客学习目录

一、引言 那么接下来几个月的时间,小编可能会一头栽进Spring系列框架里面,为啥呀? 因为小编我太菜了~~~~ 你们摸摸自己的良心问问,你们真的会用Spring吗? 了解Spring底层是怎么实现的吗? 好吧,我承认,可能大家Spring都会用,不就是复制粘贴下配置文件,写几个注解,不就完事嘛,项目照常运行呀。 如果你想提升自己、如果你想在更加的了解Spring、如果你想写出高质量的代码...

贱男 1449

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

@Autowired通过源码进行原理详解

各位看友,请注意,本文章篇幅很长,得耐心看,希望坚持。IOC,inversion of control 控制反转,有时候也叫DI,dependency injection...

田维常 2355

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

又出神作!阿里技术官再出山,操作性超强的Spring源码实践

如果你看懂了 Spring 源码,再去看 MyBatis、Spring Security 源码,你会发现这些源码都非常容易,稍微瞅几眼就懂了。 然而源码的学习是一个枯燥的过程,源码解读也是一个枯燥的过程,但是一旦你把源码搞懂了,技术上的提升也绝对是肉眼可见的,所以,去折腾一下源码绝对是有必要的,这也是你和同行拉开差距的方式之一。 本文将会从Spring基础入门、Spring项目实战再到Spring底层源码分析来介绍,希望读者们能够从中获取到对自己有用的知识,进而升职加薪。 目录 内容展示 Spring基

Java_Jishu的博客 142

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

Spring源码分析

IOC源码分析

渔阳的博客 257

如果在学习spring的时候没看过这份学习笔记+源码剖析,真的亏大了!

Spring 是一个开源的设计层面框架,它解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用。包括在此基础上衍生的 Spring MVC、 Spring Boot 、Spring Cloud 等,在现在企业中的应用越来越广泛。因此对于 Spring 框架的学习显得尤为必要。

老男孩的架构路 372

Spring源码深度解析专题篇提纲

..

weixin_38536500的博客 171

691页,41个版块,终于有阿里顶级架构师可以带我吃透Spring源码了

Spring源码的相关问题可以说是现在Java面试必问的一些问题,同时如果你没有好好的阅读过源码的话,同时又觉得源码晦涩难懂的话,只想去取其精华去其糟粕的话,那么接下来这份spring源码学习宝典你一定要好好仔仔细细的看和多刷 ,帮助非常大!

wdjnb的博客 104

又曝新作!阿里技术官再出山,操作性超强的Spring源码实践

如果你看懂了 Spring 源码,再去看 MyBatis、Spring Security 源码,你会发现这些源码都非常容易,稍微瞅几眼就懂了。然而源码的学习是一个枯燥的过程,源码解读也是一个枯燥的过程,但是一旦你把源码搞懂了,技术上的提升也绝对是肉眼可见的,所以,去折腾一下源码绝对是有必要的,这也是你和同行拉开差距的方式之一。本文将会从Spring基础入门、Spring项目实战再到Spring底层源码分析来介绍,希望读者们能够从中获取到对自己有用的知识,进而升职加薪。

m0_71777195的博客 261

spring中@Autowired注解的原理

阅读代码我们可以看到,Autowired注解可以应用在构造方法,普通方法,参数,字段,以及注解这五种类型的地方,它的保留策略是在运行时。在Spring源代码当中,Autowired注解位于包org.springframework.beans.factory.annotation之中,如上图。...

m0_46420244的博客 4944

深入剖析Spring IOC容器原理、源码与实践案例

本文深入解析了Spring IOC容器的核心原理与实现机制。首先介绍了IOC(控制反转)设计思想,将对象创建和依赖管理交给容器处理,并通过代码示例对比传统开发与IOC方式的区别。随后详细剖析了IOC容器的初始化流程,包括资源加载、BeanDefinition注册和Bean实例化三个阶段,重点讲解了依赖注入的实现原理和循环依赖的三级缓存解决方案。最后通过注解配置和XML配置两种方式演示了IOC容器的实践应用,并展示了Bean生命周期的完整管理过程。

没事学AI的博客 1103
上一篇: Java获取某一日期的前N天
下一篇: 源码解析:深入Spring中的BeanFactory
JavaWizard-M
博客等级 码龄6年 3159粉丝 148原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值