Spring源码分析之依赖注入(二)

SpringloC容器的依赖注入源码解析(10)—— populateBean的剩余逻辑(1) 我们总是喜欢瞻仰大厂的大神们,但实际上大神也不过凡人,与菜鸟程序员相比,也就多花了几分心思,如果你再不努力,差距也只会越来越大。面试题多多少少对于你接下来所要做的事肯定有点帮助,但我更希望你能透过面试题去总结自己的不足,以提高自己核心技术竞争力。每一次面试经历都是对你技术的扫盲,面试后的复盘总结效果是极好的!《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!if (mpvs!= null &&!try {// 进行属性的依赖注入。 阅读详情

一、前言

主要讲解了在依赖注入过程中, @Autowired等注解方法注入的源码解析

二、方法的注入

我们上一篇文章最后讲到了方法的注入, 保留了一个重要方法没有进行讲解, 具体如下图所示

我们点进这个方法, 具体如下图所示, 接下来我就开始为大家讲解这个方法具体的内容

下图红框部分是获取当前注入方法的入参, 因为一个方法可能有多个入参, 所以用数组接收,

然后去遍历这个数组, 分别的根据这几个参数的信息分别去 BeanFactory中找到对应的 bean

在这个遍历循环的过程当中有一个方法是很重要的, 接下来我带大家看一下这个方法的内部实现

在上图这个方法中, 入参的 DependencyDescriptor descriptor需要注意一下, 因为这个参数可以是字段或者方法参数, 但是我们去获取这个参数的信息, 只会获取其名字和类型

该方法简单流程说明:

  • 获取方法入参名字
    • 通过java反射获取的, 该方法只做了这一件事
  • 判断参数的类型(大多数情况下直接进入 else中)
  • else
    • 判断方法或属性上有没有使用 @Lazy注解

三、如果有 @Lazy注解

如果有 @Lazy注解则会进入以下方法

在 IsLazy方法中, 他会先去判断你的属性有没有 @Lazy注解, 再去判断方法的参数有没有使用 @Lazy注解

假设存在 @Lazy注解, 那么通过三元运算符会进入到 buildLazyResolutionProxy方法中, 这个方法内部主要是和 AOP相关, 后续我们会出专门的文章进行讲解, 目前暂时知道它会产生一个代理对象就可以了

简单流程说明:

  • 最开始为属性赋值, 但是因为属性是被 @Lazy注解修饰的, 所以被赋的值是一个 代理对象
  • 当真正的去执行这个 代理对象的某个方法的时候
  • 才会根据 这个代理对象字段的信息去 BeanFactory中找对应的 bean对象
  • 再去执行 bean对象对应的方法

四、如果没有 @Lazy注解

我们回到之前的方法中, 如果没有 @Lazy注解, 那么就会进入到下面的这个方法中

doResolveDependency方法是非常核心的

@Nullable
public Object doResolveDependency(DependencyDescriptor descriptor, @Nullable String beanName,
      @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

   InjectionPoint previousInjectionPoint = ConstructorResolver.setCurrentInjectionPoint(descriptor);
   try {
      // 如果当前descriptor之前做过依赖注入了,则可以直接取shortcut了,相当于缓存
      Object shortcut = descriptor.resolveShortcut(this);
      if (shortcut != null) {
         return shortcut;
      }

       
      Class<?> type = descriptor.getDependencyType();
      // 获取@Value所指定的值
      Object value = getAutowireCandidateResolver().getSuggestedValue(descriptor);
      if (value != null) {
         if (value instanceof String) {
            // 占位符填充(${})
            String strVal = resolveEmbeddedValue((String) value);
            BeanDefinition bd = (beanName != null && containsBean(beanName) ?
                  getMergedBeanDefinition(beanName) : null);
            // 解析Spring表达式(#{})
            value = evaluateBeanDefinitionString(strVal, bd);
         }
         // 将value转化为descriptor所对应的类型
         TypeConverter converter = (typeConverter != null ? typeConverter : getTypeConverter());
         try {
            return converter.convertIfNecessary(value, type, descriptor.getTypeDescriptor());
         }
         catch (UnsupportedOperationException ex) {
            // A custom TypeConverter which does not support TypeDescriptor resolution...
            return (descriptor.getField() != null ?
                  converter.convertIfNecessary(value, type, descriptor.getField()) :
                  converter.convertIfNecessary(value, type, descriptor.getMethodParameter()));
         }
      }

      // 如果descriptor所对应的类型是数组、Map这些,就将descriptor对应的类型所匹配的所有bean方法,不用进一步做筛选了
      Object multipleBeans = resolveMultipleBeans(descriptor, beanName, autowiredBeanNames, typeConverter);
      if (multipleBeans != null) {
         return multipleBeans;
      }

      // 找到所有Bean,key是beanName, value有可能是bean对象,有可能是beanClass
      Map<String, Object> matchingBeans = findAutowireCandidates(beanName, type, descriptor);
      if (matchingBeans.isEmpty()) {
         // required为true,抛异常
         if (isRequired(descriptor)) {
            raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
         }
         return null;
      }

      String autowiredBeanName;
      Object instanceCandidate;

      if (matchingBeans.size() > 1) {
         // 根据类型找到了多个Bean,进一步筛选出某一个, @Primary-->优先级最高--->name
         autowiredBeanName = determineAutowireCandidate(matchingBeans, descriptor);
         if (autowiredBeanName == null) {
            if (isRequired(descriptor) || !indicatesMultipleBeans(type)) {
               return descriptor.resolveNotUnique(descriptor.getResolvableType(), matchingBeans);
            }
            else {
               // In case of an optional Collection/Map, silently ignore a non-unique case:
               // possibly it was meant to be an empty collection of multiple regular beans
               // (before 4.3 in particular when we didn't even look for collection beans).
               return null;
            }
         }
         instanceCandidate = matchingBeans.get(autowiredBeanName);
      }
      else {
         // We have exactly one match.
         Map.Entry<String, Object> entry = matchingBeans.entrySet().iterator().next();
         autowiredBeanName = entry.getKey();
         instanceCandidate = entry.getValue();
      }

      // 记录匹配过的beanName
      if (autowiredBeanNames != null) {
         autowiredBeanNames.add(autowiredBeanName);
      }
      // 有可能筛选出来的是某个bean的类型,此处就进行实例化,调用getBean
      if (instanceCandidate instanceof Class) {
         instanceCandidate = descriptor.resolveCandidate(autowiredBeanName, type, this);
      }
      Object result = instanceCandidate;
      if (result instanceof NullBean) {
         if (isRequired(descriptor)) {
            raiseNoMatchingBeanFound(type, descriptor.getResolvableType(), descriptor);
         }
         result = null;
      }
      if (!ClassUtils.isAssignableValue(type, result)) {
         throw new BeanNotOfRequiredTypeException(autowiredBeanName, type, instanceCandidate.getClass());
      }
      return result;
   }
   finally {
      ConstructorResolver.setCurrentInjectionPoint(previousInjectionPoint);
   }
}

resolveMultipleBeans方法

我们看一下 resolveMultipleBeans详情

可以看到, 他会根据你属性注入的类型不同来进行不同的操作, 会去直接匹配对应的 bean方法,不在进行进一步的筛选了

例如当我们属性注入的类型为 Map的时候, 它会强制要求key为String类型, 并去寻找相应的 bean

具体的如下所示, 他会根据 bean的类型去找 bean的名字

Map<String, Object> matchingBeans = findAutowireCandidates(beanName, valueType,
      new MultiElementDescriptor(descriptor));

然后去判断 如果没有找到 Bean则抛出异常

核心的findAutowireCandidates方法

流程信息

  • 找出BeanFactory中类型为type的所有的Bean的名字,注意是名字,而不是Bean对象,因为我们可以根据BeanDefinition就能判断和当前type是不是匹配,不用生成Bean对象
  • 把resolvableDependencies中key为type的对象找出来并添加到result中
  • 遍历根据type找出的beanName,判断当前beanName对应的Bean是不是能够被自动注入
  • 先判断beanName对应的BeanDefinition中的autowireCandidate属性,如果为false,表示不能用来进行自动注入,如果为true则继续进行判断
  • 判断当前type是不是泛型,如果是泛型是会把容器中所有的beanName找出来的,如果是这种情况,那么在这一步中就要获取到泛型的真正类型,然后进行匹配,如果当前beanName和当前泛型对应的真实类型匹配,那么则继续判断
  • 如果当前DependencyDescriptor上存在@Qualifier注解,那么则要判断当前beanName上是否定义了Qualifier,并且是否和当前DependencyDescriptor上的Qualifier相等,相等则匹配
  • 经过上述验证之后,当前beanName才能成为一个可注入的,添加到result中

源码讲解

我们进入这个方法, 里面的注释是比较清楚的, 接下来主要是针对一些方法的讲解

beanNamesForTypeIncludingAncestors方法

  • 先根据自己的类型去 BeanFactory中找 bean的名字
  • 如果有 父BeanFactory, 就去 父BeanFactory中找
  • 然后将两个集合合并起来返回

怎么根据 Bean的类型去找

我们进入 getBeanNamesForType方法, 具体如下图所示

doGetBeanNamesForType方法

这个方法太长了, 而且我看着真的蒙, 简单讲一下流程, 感兴趣的话大家自己看一下:

  • 遍历 BeanDefinition
  • 判断bean名字前有没有&符号, 有的话去处理掉
  • 拿取 BeanDefinition的属性判断当前的是否匹配

返回

我们回到本方法的开头, 只要知道这个方法是从 BeanFactory中找出和 requiredType所匹配的 beanName, 仅仅是 beanName, 这些 bean不一定经过了实例化, 只有到最终确定某个 Bean了, 如果这个Bean还没有实例化才会进行实例化

resolvableDependencies

在 Spring启动的时候就会忘这个 map中存东西,

这个 map具体的存储过程如下图所示: 后续讲Spring启动源码的时候会讲

Bean对象加入到集合

然后去遍历这个 map, 获取到 key也就是 Bean类型, 判断有没有相同的 Bean类型, 如果有就把对应的对象加入到我们的返回数组中

遍历判断是不是自己注入自己

  • 如果不是自己注入自己,则判断该candidate到底能不能用来进行自动注入
  • 注入非自己
  • 如果有多个candidate 最终将匹配成功 candidate加入到 result
  • 因为有多个, 且result不为空
  • 所以直接返回 result

result.isEmpty()

  • 假设有多个 candidate, 且都不匹配, result == null
  • 则会去判断需要的类型是不是 Map, 数组之类的
  • 中间那个for循环用的很少 , 就先不看了
  • 如果匹配的是自己, 就将自己添加到result中

返回

然后去判断 如果没有找到 Bean则抛出异常

如果找到了多个 Bean

如图所示, 如果根据 beanName找到了多个 Bean那么该 if判断则为 true

determineAutowireCandidate方法

在这个方法中, 我们先去获取他的类型, 获取类型之后执行 determinePrimaryCandidate方法, 下图是这个方法的详情

上图中的方法经历了以下几个步骤:

  • 遍历 map获取对应的 beanName和 ( bean对象或 Class类)
  • isPrimary方法, 判断这多个 Bean有没有否实现了 @isPrimary注解
  • 如果都实现了 @isPrimary注解则抛出异常
  • 如果只有一个实现了 @isPrimary注解则使用这个 Bean

方法结束, 返回上一层 determineAutowireCandidate方法

途中红框部分的方法讲解完毕, 接下来它去寻找了我们的返回值, 如果都没有实现 @Primary注解, 那么继续往下走

determineHighestPriorityCandidate方法

方法流程如下:

  • 遍历map
  • 取当前某个Bean的优先级是什么
  • 获取 @Priority注解, 方法在下图红框位置

@Priority 该注解不能使用在方法上, 只能使用在类上面

@Order在依赖注入中是没有去使用判断的

方法结束, 返回上一层 determineAutowireCandidate方法

如上图所示, 我们继续往下走, 最后才是根据名字去判断 bean对象的

通过源码可以看到 @Resource 和 @Autowired的区别 如果有多个同名beanName, 那么@Autowired 会先去寻找有没有哪个 bean是有 @Primary注解的, 如果都没有, 则去寻找有没有哪个类上是有 @Priority优先级注解的, 如果都没有则会去按照名称查找 这个面试题在刚毕业的时候也是经常被问到的, 以前只知道答案, 这次通过源码对其的解答也更加清晰明了了

返回

接下来返回到下面红框的位置, 继续玩下走

如果没有找到对象, required == true抛出异常, 如果不为 true则返回 null, 然后赋值

如果只找到了一个 Bean

那么直接为之前定义的 autowiredBeanName 和 instanceCandidate进行赋值

如果找到了Bean

如果找到了Bean , 则进行记录

判断 instanceCandidate是不是一个类

如果是一个类, 那么获取这个类的 bean

去判断这个类型是不是 NullBean

NullBean的定义代码如下所示, 当以下面的方式定义一个 bean的时候, 这个bean存在 map中的 key为 JuejinService, value为 NullBean

@Bean
public JuejinService juejinService(){
   return null;
}

相关判断代码如下所示

最后返回 over

最后红框判断的是期望类型和实际获取到的类型是否一致问题, 就不详细解释了

工业质检实战:如何用MVTec AD数据集训练你的第一个无监督异常检测模型 本文提供了一份基于MVTec AD数据集的工业质检实战指南,详细介绍了如何从零开始训练一个无监督异常检测模型。内容涵盖数据预处理、模型架构选型(如CAE、GAN与特征字典方法)、特征提取、损失函数设计以及关键的阈值确定与后处理流程,旨在帮助工程师快速掌握将AI技术落地于实际产线质检的核心步骤与调参经验。 阅读详情

相关推荐

树莓派5外接RTX显卡:从PCIe到驱动的完整踩坑指南

在ARM架构与GPU加速的交汇点,树莓派5凭借其PCIe接口为DIY爱好者打开了外接独立显卡的大门。然而,PCIe x1的带宽限制、供电差异以及NVIDIA驱动在ARM Linux上的兼容性,使得这一组合成为一场高强度的系统底层排错训练。从理解PCIe总线原理、驱动加载机制到CUDA环境配置,每一步都充满挑战。本文以工程实践视角,梳理外接RTX显卡的完整流程、常见故障与性能瓶颈,并探讨其在边缘计算、AI推理等场景下的真实价值,帮助你理性评估这一实验性方案的可行性与替代路径。

chubaisheng8627的博客 351

Spring源码学习(八)-- 依赖注入源码解析(下)

上篇文章分析了Spring中的自动注入(byName,byType)和@Autowired注解的工作原理以及源码,@Autowired注解依赖注入其中注入点注入,无论是属性注入还是方法注入都有一个相同的方法 org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveDependency @Nullable Object resolveDependency(DependencyDescriptor desc..

学习笔记 1671

gem5 run parsec2.1 ---- 亲测跑通教程

使用gem5模拟仿真parsec2.1,排除了各种bug,成功跑通,亲测有效!!!

m0_55539563的博客 1547

Spring IoC 依赖注入-resolveDependency

目录resolveDependency 是 Spring 进行依赖查找的核心 API。弄明白了 resolveDependency,基本上依赖注入的问题也就搞明白了一半。resolveDependency 本质是根据类型查找依赖,调用 beanFactory#beanNamesForType 方法根据类型查找依赖名称。认知一下,与依赖查找的相关 API:resolveDependency:支持 Optional、延迟注入、懒加载注入、正常注入。

z69183787的专栏 1211

群晖NAS断电后IP变了?3步搞定静态IP设置(附Linux挂载指南)

本文针对群晖NAS因断电重启导致IP地址变化的问题,提供了从根源到实践的完整解决方案。核心内容包括如何为NAS配置静态IP以彻底解决连接中断,并详细讲解了在Linux系统中通过NFS协议稳定挂载NAS共享文件夹的步骤与指南,确保网络存储服务持久可靠。

weixin_29271263的博客 858

玩转肺癌目标检测数据集Lung-PET-CT-Dx ——①从TCIA获取影像数据集

该目标检测公共数据集源自 The Cancer Imaging Archive(TCIA),是肿瘤研究方面的著名的医学影像公开数据库。 数据以 DICOM 格式存储,由肺癌受试者的 CT 和 PET-CT DICOM 图像组成。

takedachia的博客 1万+

【Spring源码分析】从源码角度去熟悉依赖注入(二)

筛选6步记住:@Value ---- autowireCandidate 元数据属性要为 true ----- @Qualifier 限定符若有需匹配 ------- 多Bean的话 @Primary --------@Priority ------属性名或者参数名匹配

qq_63691275的博客 1937

Unity3d移动端性能优化

以下条目主要针对移动端,大部分也适合PC端 一、Profiler的使用 1.性能优化应贯穿项目开发的全过程,如需求(性能能不能达到要求)、设计、开发、测试等。不能开发结束才优化性能。 2.官方推荐的优化工具是【Window】->【Profiler】 3.确认瓶颈是CPU-bound(Gfx.WaitForCommands)还是CPU-bound(Gfx.WaitForPresent) 4.内存分析使用Memory Profiler 二、内存优作 5.减少内存收集的影...

zouxin_88的专栏 3061

跟我学Spring之自定义bean容器提升代码可读性

转发大佬的文章Mark以便于学习 链接请见:跟我学Spring之自定义bean容器提升代码可读性 开发中经常有这样的场景: 根据某个类型标识走不同的业务逻辑,通常我们会使用if(type.equals(xxxxx)) 或者 switch语句来进行逻辑处理。 这样做当然是没什么问题的。 当业务逻辑变得越来越复杂,类型标识增多之后,难免会出现if判断增加,或者switch case分支变多,这样的代码往往会过于冗长,代码重复性较大,或者说逼格不够高。 本文介绍一种基于自定义Bean容器的开发方式..

Little Feel的博客 370

Android Framework SurfaceFlinger面试题及参考答案

请简述 SurfaceFlinger 在 Android 系统中的作用。 SurfaceFlinger 是 Android 系统中一个非常关键的服务。它主要负责将多个应用程序的 Surface 合成到一个屏幕显示内容中。 从应用程序的角度来看,每个应用都有自己的 UI 界面,这些 UI 界面实际上是由一系列的图层(Surface)构成。例如,一个应用可能有背景图层、按钮图层、文本图层等。应用通过向 SurfaceFlinger 提供这些 Surface 来请求显示。 SurfaceFl

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

LabVIEW实现TCP通信

在本节中,我们将简要探讨TCP通信的基础知识,并以工业物联网平台TLINK中的云端设备数据发布设计为例,详细阐述在互联网环境下TCP客户端应用程序设计的基本方法。

不脱发的程序猿 1965

「Spring-IoC」源码分析二依赖注入&依赖循环

书接上文我对IoC感兴趣的2个点分别是 IoC是怎么获取bean信息,并管理bean的 IoC引以为豪的依赖注入 IoC是怎么解决循环依赖的(没错完全是因为网上说面试爱问) 现在已经解决了第一个问题了,下面来分析下第二个问题–依赖注入 依赖注入简单来说就是自己创建对象交给Spring容器管理。那肯定就有以下几个步骤了 创建对象 将对象所依赖的对象注入进来 怎么解决循环依赖的问题的 本篇也将围绕着三点展开了。 ps:源码分析乃个人总结,如果有任何不对的地方,欢迎联系我讨论 创建对象 在上一篇中已

Nortyr的博客 714

ESP32S3接入讯飞在线语音识别教程及配套源代码

本文介绍了如何使用ESP32-S3开发板实现讯飞在线语音识别功能。首先,需要准备硬件设备,包括ESP32-S3开发板、麦克风模块、MicroSD卡模块和扬声器模块。接着,安装Arduino IDE并配置ESP32-S3开发环境,注册讯飞开放平台账号并获取API凭证。然后,通过I2S接口连接麦克风模块,并编写代码实现语音录制、Base64编码、API请求和识别结果处理。代码包括初始化WiFi、麦克风、系统时间,以及录制语音、发送请求、解析响应等功能。最后,通过按键触发录音,并将识别结果输出到串口。

2401_88800025的博客 748

Spring源码分析(二)bean的实例化和IOC依赖注入

前言 我们知道,IOC是Spring的核心。它来负责控制对象的生命周期和对象间的关系。 举个例子,我们如何来找对象的呢?常见的情况是,在路上要到处去看哪个MM既漂亮身材又好,符合我们的口味。就打听她们的电话号码,制造关联想办法认识她们,然后…这里省略N步,最后谈恋爱结婚。 IOC在这里就像婚介所,里面有很多适婚男女的资料,如果你有需求,直接告诉它你需要个什么样的女朋友就好了。它会给我们提供一个MM...

七夜zippoe的博客 289

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Spring -- 依赖注入源码分析(二)

继续http://blog.youkuaiyun.com/gaopeng0071/article/details/54582979 之后我们来分析使用注解进行注入,源码是如何工作的。参考资料:http://blog.youkuaiyun.com/chjttony/article/details/6301591继上一篇文章的 AbstractAutowireCapableBeanFactory.class类,popula

GP的空间 719

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

python ioc_Spring源码分析(二)bean的实例化和IOC依赖注入

前言我们知道,IOC是Spring的核心。它来负责控制对象的生命周期和对象间的关系。举个例子,我们如何来找对象的呢?常见的情况是,在路上要到处去看哪个MM既漂亮身材又好,符合我们的口味。就打听她们的电话号码,制造关联想办法认识她们,然后...这里省略N步,最后谈恋爱结婚。IOC在这里就像婚介所,里面有很多适婚男女的资料,如果你有需求,直接告诉它你需要个什么样的女朋友就好了。它会给我们提供一个MM,...

weixin_35900818的博客 274

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

spring5源码分析系列(八)——基于XML的依赖注入(二)

    前言:上一篇讲到了populateBean方法对Bean属性的依赖注入,此篇继续后面的内容。 7.BeanDefinitionValueResolver解析属性值     当容器在对属性进行依赖注入时,如果发现属性值需要进行类型转换,比如属性值是容器中另一个Bean实例对象的引用, 则容器首先需要根据属性值解析出所引用的对象,然后才能将该引用对象注入到目标实例对象的属性上去,对属性进行解析...

yaofengdoit的博客 190

Spring5源码分析(三) IOC容器的依赖注入— 基于XML的依赖注入(二)

四、createBeanInstance 方法创建Bean的java 实例对象   在createBeanInstance方法中,根据指定的初始化策略,使用静态工厂、工厂方法或者容器的自动装配特性生成java实例对象,创建对象的源码如下: //创建Bean的实例对象 protected BeanWrapper createBeanInstance(String beanName, Root...

mokingone的专栏 527

@xmlelement 注解在属性 方法上的区别_Spring源码分析(二)依赖注入及方法注入...

上篇文章讲了官网中的 1.2,1.3 两小节,主要是涉及了容器,以及 Spring 实例化对象的一些知识。这篇文章继续 Spring 官网,主要是针对 1.4 小节,主要涉及到 Spring 的依赖注入。虽然只有一节,但是涉及的东西确不少。 依赖注入根据官网的介绍,依赖注入主要分为两种方式:构造函数注入setter方法注入我们分别对以上两种方式进行测试,官网上用的XML的方式,我这里就采用注解的方...

weixin_33179060的博客 2065

Spring基础学习笔记(二)--依赖注入--spring源码分析--Spring注解

Spring DI 依赖注入 三种注入方式介绍 DI (Dependency Injection) 依赖注入 依赖注入,即组件之间的依赖关系由容器在系统运行期来决定,也...

m0_47419463的博客 165

spring依赖查找、依赖注入深入学习及源码分析

延迟查找,我个人认为主要是给架构开发者使用的。非常典型的一个使用场景,就是SpringBoot里的自动配置,可以看看LettuceConnectionConfiguration这个类,这个类用于创建RedisClient。显然,RedisClient的创建是要根据用户的需求来创建的。有些属性是必须的,可以在配置文件里配置,比如ip,port这种。Lettuce在创建RedisClient的时候,会从配置文件里读取这些数据来创建RedisClient。

秃了也弱了 1409

Spring源码分析の依赖注入(@AutoWired模式)

在Spring中,进行依赖注入最常见的方式是@AutoWired和@Resource。其中默认按类型(byType)查找,如果找到多个匹配的Bean,则按名称(byName)查找。而@Resource是先根据名称查找,如果(根据名称)查找不到,再根据类型进行查找。@AutoWired在源码中的体现,主要在于:在实例化后,依赖注入前预先寻找注入点在实例化后,初始化前,进行注入Spring 在实例化后,初始化前,扫描标记了该注解的属性或者方法,作为注入点缓存。

西岭千秋雪的博客 1293

Spring源码之依赖注入(一)

前面我们已经分析完了Bean的生命周期,包括BeanDefinition的扫描与注册,Bean的初始化和销毁等。今天就来分析依赖注入(DI)相关的源码。依赖注入: Dependency Injection,它是 spring 框架核心 IOC 的具体实现,具体点就是依赖关系的维护称之为依赖注入。我们的程序在编写时, 通过控制反转(IOC), 把对象的创建交给了 spring,但是代码中不可能出现没有依赖的情况。IOC 解耦只是降低他们的依赖关系,但不会消除。例如:我们的业务层仍会调用持久层的方法。

qq_43456605的博客 1279

Spring源码分析 IOC依赖注入

Spring源码分析 IOC依赖注入 1 基于上篇 Spring源码分析 Bean创建和获取 依赖注入是在beaa创建时候完成,bean的创建触发过程如下 单例模式非延迟加载的对象,会在IOC容器初始化的时候被创建且初始化 非单例模式或者延迟加载的对象,应用第一次向容器索要该Bean对象的时候被创建且初始化 基于创建bean源码分析IOC依赖注入 public Object getBean(...

zahary 346

Spring依赖注入源码分析

Spring 依赖注入源码解析, 入口:DefaultListableBeanFactory#resolveDependency 判断是否懒加载,懒加载直接返回CGLIB代理对象; doResolveDependency 开始进行依赖注入; resolveMultipleBeans 判断注入的对象是否是集合类型(Stream,Collection,Array,Map) ,是的话直接return ; findAutowireCandidates 根据类型查找所有匹配到的bean,返回一个Map对象;

Quan 793

spring源码系列(二)——毁三观的spring自动注入

比如提到spring的自动注入作为一个java程序员肯定自信无比了解;但是笔者要说的自动注入可能会和你理解有很大出入。 首先搞明白什么是自动注入,自动注入也可以叫做自动装配(springboot也有一个自动装配但是我认为翻译的不够准确,springboot的应该叫做自动配置和这里说的自动注入是两回事,笔者不是什么大牛或者权威;所以读者如果你坚持认为springboot也叫自动装配那也无可厚非,只...

java_lyvee的专栏 3万+
上一篇: 《Java编程思想》读书笔记分享
下一篇: Spring源码分析之依赖注入(一)
java_lujj
博客等级 码龄4年 18粉丝 152原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值