【转】关于Spring的两三事:万物之始—BeanDefinition

关于Spring的两三事:万物之始—BeanDefinition 道家有云:“道生一,一生二,二生三,三生万物。”这句话简单理解就是,世间万物皆是由道衍生出来的,而道则是对万物的一种极致抽象。在不断深入学习和使用Spring框架的过程中,愈发觉得在Spring框架的设计理念中随处可见前面提到的道家理念。在之前的学习中我们有提到Spring框架中最核心的两个部分,一个是IoC容器,一个是AOP模块,其余功能都是基于这两个核心功能构建起来的。而在IoC容器和AOP模块这两个核心功能中,后者又是基于前者来实现相应的功能。... 阅读详情

一、前言

道家有云:“道生一,一生二,二生三,三生万物。”这句话简单理解就是,世间万物皆是由道衍生出来的,而道则是对万物的一种极致抽象。

在不断深入学习和使用Spring框架的过程中,愈发觉得在Spring框架的设计理念中随处可见前面提到的道家理念。在之前的学习中我们有提到Spring框架中最核心的两个部分,一个是IoC容器,一个是AOP模块,其余功能都是基于这两个核心功能构建起来的。而在IoC容器和AOP模块这两个核心功能中,后者又是基于前者来实现相应的功能。至此,我们不难得出一个不是那么准确的结论,即Spring所提供的全部功能都是通过IoC容器生成的各式对象来实现的。那么,这些各式各样的对象又是如何生成的呢?

遍观网络上大部分Spring系列或者关于Spring IoC容器的博客在谈及Spring Bean生成过程时都喜欢围绕Bean的生命周期进行细致分析,但在Bean成员变量是如何确定、Bean中为什么会包含某些注解等一些Bean定义来源问题以及相应处理流程的讲解上经常是轻描淡写一笔带过(当然笔者之前学习的时候也喜欢干这种事情,哈哈哈~),导致对于Spring中“万物”生成的流程总是感觉理解得不够透彻,好像缺少了什么。其实再往前深挖一步我们就可以得到答案,上面博客中关注的Bean生命周期的分析更多的是针对Bean成员变量设置以及方法代理等流程的分析,而对于Bean定义的设计以及生成的流程却鲜少进行分析讨论。为了更好地理解Spring容器创建对象的过程,我们需要追本溯源,去探索一下Bean对象的源头BeanDefinition的运作原理。

二、为什么需要BeanDefinition?

让我们先抛开IoC容器,抛开Spring,先回归最基本的对象生成流程(需要注意,这里我们谈论的对象生成更多的是属于编码使用层面,而非JVM层面)。从以往学习的经验来看,对象的生成可以分为两步:实例创建和属性赋值。前者创建了一个空的对象,后者则是对这个空对象的成员变量进行赋值处理。如果让我们使用人工的方式来处理这两步其实非常简单,先通过new关键字来创建目标类的实例,然后根据我们的实际需要对目标类实例中的成员变量进行逐一赋值。这里可以通过下面的例子简单感受一下:

        // 创建实例
        Person person = new Person();
        // 进行对象成员变量赋值
        person.setName("test");
        person.setGender("male");

但是当我们尝试使用代码方式 (即编程式) 来对上述两个步骤进行逻辑抽象时就会发现这其中存在许多难点。

首先,我们遇到的第一个也是最重要的一个问题:应该创建哪个类型的实例? 之所以会遇到这样一个问题主要是Java面向对象语言中的多态特性导致的,即父类引用可以指向子类实现。基于这一特性,我们在进行对象实例化时需要明确指定使用父类或者子类进行实例化,其中如果父类是抽象类或者接口则必须使用指定子类来进行对象的实例化。这就意味着我们需要在对该关联关系进行存储以便在对象实例化时能够按照对应关系进行实例化。

第二个问题:在每次使用该对象时是否需要创建新的对象? 即是否需要使用单例模式?在我们实际开发过程中一般会有两种类型的对象,一种是只会存在于一次请求处理过程中的短周期对象(即每次使用都需要创建新的对象),一种是每次请求使用的都是同一个实例的全局单例对象。前者一般用于进行数据的临时存储,后者一般用于提供通用的数据处理能力。同样,在使用编程式方式来创建对象时我们也需要对该对象创建方式进行存储。

第三个问题:如何使用类提供的构造函数进行对象的创建? 其实这个问题的难点是在于如何使用有参构造函数来完成对象实例的创建。当我们使用无参构造函数时,可以很简单地创建实例而不需要考虑其他问题。但当我们准备使用有参构造函数时,就需要考虑如何获取函数参数列表中每个参数的对象实例,即需要如何设置相应参数哪种类型的对象实例。分析到这里可以发现,我们又绕回到了第一个问题。和第一个问题一样,要想正确地使用构造函数完成预期的实例创建,我们就需要记录构造函数的参数列表和对应参数需要设置的实例对象。

由第三个问题可以引申出第四个问题:如果目标类型只提供了无参构造函数,我们需要如何设置对象实例的成员变量? 这个问题可以说是第三个问题的变种,只不过将成员变量设置的时机由构造函的调用阶段延后至使用对象setter方法来设置成员变量阶段。

除了上面的问题,还有其他一些需要考虑的问题,这里笔者就不一一列举说明了。但是通过上面的分析我们不难得出一个结论:要想通过编程式的方式来自动化地完成指定对象的实例化和赋值处理,我们需要抽象出一个能够描述/存储对象实例内部信息的类型。

分析完最基本的对象生成流程,让我们重新回到Spring对Bean的管理功能中。此时我们会发现,其实Spring的Bean管理就是通过编程式的方法来统一管理Bean的生成和使用,在这一过程中对象的创建和赋值流程完全由框架本身控制而非由开发人员自主控制(即我们常说的控制反转)。就如同我们上面分析的一样,为了实现这一能力,Spring设计并使用BeanDefinition来进行目标对象实例信息的描述。基于BeanDefinition提供的对象实例信息,并结合Java提供的反射机制,Spring实现了道生一以至衍生万物的功能。

注意:下文中的源码均是基于SpringBoot 2.6.10版本进行分析

三、如何生成BeanDefinition?

在上一小节中我们通过分析使用编程式方法创建对象存在的问题去探索了一下BeanDefinition的设计意义,但要想真正使用BeanDefinition,我们还需要了解一下它的生成流程。

1. 普通开发者的BeanDefinition生成流程设计

同样的,让我们先抛开Spring源码本身,以一个开发者的身份思考一下如果要实现生成BeanDefinition这样一个需求需要完成哪些功能。根据上面的分析和我们日常开发的使用经验不难发现,要想生成BeanDefinition需要完成以下两个功能:

  • 确定项目中哪些类需要生成BeanDefinition
  • 基于目标类对BeanDefinition进行赋值处理

我们先来看一下第一个功能:确定项目中需要生成BeanDefinition的类。从我们日常的开发中可以发现并不是所有的类都需要通过Spring来进行创建和管理,比如DO、VO这些用于数据传输的类,再比如一些提供静态方法的工具类,这些类要么是在需要使用的地方由开发人员主动地创建并使用,要么就是不需要实例化直接使用当前类的静态方法。那么我们应该如何确定需要生成的BeanDefinition的类呢?这里我们需要将其拆分成两步完成,第一步,找到项目中所有由开发人员自定义的类,第二步,根据标识来区分这些自定义的类哪些是需要生成BeanDefinition的。前者可以通过包名扫描出所有属于这个项目的类型,后者可以通过特殊的注解来对相应的类型进行标识。

让我们接着来看一下第二个功能:基于目标类对BeanDefinition进行赋值处理。从上文的分析中我们可以知道BeanDefinition当中存储的都是用于去生成对象实例的类型信息,而要想在运行时去获取一个类型的相关信息相信大部分人的第一反应基本就是通过反射机制来实现 (为什么要说大部分人,这是因为Spring的开发人员并没有采取这一方案,在下面的源码分析阶段我们会具体了解一下其中的原因) 。通过反射机制我们能够获取到当前对象的类型信息、当前对象的注解、依赖的成员变量以及成员变量的注解等等大部分需要的类型信息,然后我们就可以将这些需要的类型信息赋值到BeanDefinition当中。

以上是我们作为一个开发人员基于生成BeanDefinition这样一个需求做出的技术方案揣测,下面让我们结合源码来具体看一下Spring是如何设计生成BeanDefinition的技术方案。

2. Spring开发者的BeanDefinition生成流程设计

从SpringBoot项目的启动类开始向内逐层debug,我们会找到自定义类型的BeanDefinition生成入口org.springframework.context.annotation.ClassPathBeanDefinitionScanner#doScan (需要注意,这里特别标注了这里的入口是非Spring框架、非二方包内的类型的BeanDefinition生成入口) 。具体可以参考下图:

首先我们来看下方法参数列表中的basePackages。在逐层debug的过程中我们可以看到方法入参中basePackages会通过两种方式获取到,一种是缺省情况下会使用启动类所在的包名作为basePackage,另一种则是从@ComponentScan注解的设置当中获取。需要注意的是,如果准备使用第二种方式来自定义设置basePackages,在我们实际使用SpringBoot时并不是直接使用@componentScan来进行basePackages设置的,而是通过@SpringBootApplication注解的scanBasePackages或scanBasePackageClasses参数来进行设置的。

在了解到basePackages的由来之后我们再来看下上面的方法,可以看到上面的方法实际上主要做了两件事:

  • 根据basePackages获取指定自定义类的BeanDefinition实例;
  • 基于生成BeanDefinition集合进行额外的包装,并将这些BeanDefinition注册到上下文当中;

这里我们主要探究一下第一部分内容的实现,从上面的代码中可以看到该部分内容的逻辑都放置在public Set<BeanDefinition> findCandidateComponents(String basePackage)方法当中。通过实际的debug会发现流程最终会进入到该方法内部的scanCandidateComponents(basePackage)中。该方法的具体内容如下:

从上面的代码中可以看出,Spring的开发者们确实和我们之前猜测的一样,基于basePackages来扫描出所有有可能需要生成BeanDefinition的类文件。但是和我们猜测的不同,这里扫描的不是单纯的类全限定名,而是class文件的文件路径,同时最终生成类型的元数据信息时并没有使用反射机制,而是使用了读取.class文件字节码的方式(这部分逻辑在org.springframework.asm.ClassReader#accept(org.springframework.asm.ClassVisitor, int)方法中处理,这里不展示具体的代码内容)。相比一些同学会产生疑惑,为什么没有使用简单好用的反射机制,而是使用了极其复杂难用的读取字节码的方式来获取类型的元数据信息?这主要是由于JVM本身特性导致的,在实际的运行过程中,JVM并不会时时刻刻加载全部的类型信息,只会将部分需要使用到的类型加载到虚拟机内存当中。这就意味着在项目启动的初始化过程中,JVM当中可能并没有将对应类型加载到内存当中,使用反射机制并不能获取到对应类型的元数据信息。同时,从效率上来讲通过字节码的方式比使用反射机制会更高。

除此以外,在实际生成BeanDefinition时,Spring框架做了进一步的判断和拦截。和我们上面的分析相同,基于basePackages的.class文件扫描会将所有自定义类型都扫描出来,这其中就包含不少不需要生成BeanDefinition的类型。从上面的代码中我们可以看到,实际的判断和拦截是通过isCandidateComponent(metadataReader)和isCandidateComponent(sbd)来完成的。第一个方法中通过基于注解的过滤器(excludeFilter)和包含器(includeFilter)来判断当前类型是否需要生成BeanDefinition,第二个方法在第一个方法的判断基础上进一步针对BeanDefinition进行了判断,如果当前类型属于接口、抽象类或者封闭类(enclosing class) 则舍弃当前BeanDefinition。补充第二判断的主要原因是,开发者在实际开发时可能会将注解标注在不能生成对象实例的类(比如上面提到的三种类型)上,即单纯靠注解进行判断是不完全可信的。

在isCandidateComponent(metadataReader)方法中的包含器会基于@Component注解来判断是否包含当前类型的元数据,根据这一条件,使用包含@Component注解的注解对类进行标记时也会被包含器包含(比如@Configuration、@Service、@Controller、@RestController等)

以上即为根据basePackages获取指定自定义类的BeanDefinition实例的实现过程,在这一过程中Spring还完成了类型元数据相关信息的赋值处理。而在第二部分中更多是基于Spring自身设计以及其他功能的额外信息设置(包含scope、init方法、destory方法等信息的设置),有兴趣的同学可以自行进行源码的阅读,这里笔者就不过多分析了。

四、BeanDefinition的使用

铺垫了这么久,我们终于来到了BeanDefinition使用环节的分析。在Spring框架当中,对于BeanDefinition的使用主要分为两个方面:

  • 基于BeanDefinition进行Bean对象的创建;
  • 基于BeanDefinition对Bean对象进行额外的加工处理(诸如Bean属性设置、使用BeanPostProcessor对Bean进行额外处理等);

在本篇文章中我们会将目光聚焦在第一个方面,对于第二个方面网上已经有太多的博客进行过分析,这里就不加赘述了(其实我们经常看到的对于Bean生命周期的分析其实就是这里所说的第二个方面的一部分)。

从第一小结的分析当中我们可以看到如果不使用new关键字的方式来进行对象实例的创建,我们就需要使用反射机制来完成。使用反射机制的目的是为了获取到目标类型的构造器Constructor<T> ctor,然后通过构造器方法的Constructor#newInstance来创建对应的实例。在Spring框架中就是使用了反射机制中的相应流程来完成对于Bean实例的创建,具体方法org.springframework.beans.BeanUtils#instantiateClass(java.lang.reflect.Constructor<T>, java.lang.Object...)如下:

这个方法的内部逻辑非常简单,我们需要关注的是方法的参数列表,或者说是该方法参数列表中的值是从什么地方获取到的。为了解决这个问题,我们需要向上回溯,回到org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBeanInstance方法:

从上面展示的代码中我们可以归纳出三种利用BeanDefinition生成对象实例的情况:

  • 使用开发自定义的创建实例的方法,即代码中展示的obtainFromSupplier(instanceSupplier, beanName)和instantiateUsingFactoryMethod(beanName, mbd, args),前者由开发自定义所需的Supplier<?>,后者则需要开发实现对应的工厂方法;
  • 使用类默认的无参构造函数进行对象实例的创建,即代码中的instantiateBean(beanName, mbd)方法;
  • 使用特定的构造函数进行对象实例的创建,即代码中的autowireConstructor(beanName, mbd, ctors, args)方法;

第一种情况是通过开发者自行控制,是Spring提供一个扩展点,这里不需要做过多关注。第二种方式和第三种方式从本质上来说其实是一种方法,即使用反射机制中的构造器来进行对象实例创建,两者的区别在于一个使用的是默认的无参构造函数,另一个则是通过读取BeanDefinition中指定的首选构造器或候选构造器来完成对象实例的生成。

这里需要补充一点,在AbstractAutowireCapableBeanFactory#createBeanInstance方法的第一行Class<?> beanClass = resolveBeanClass(mbd, beanName);中可以看到,这里通过BeanDefinition进行了目标类型的加载处理,即保证目标类型已经加载到JVM当中,这也解释了为什么后续方法可以使用反射机制来生成对象实例。

在这里我们可以解决BeanUtils#instantiateClass参数列表中第一个参数Constructor<T>的来源问题,但是貌似并没有找到解决第二个参数构造函数的参数列表的来源。这里笔者使用了貌似是因为如果我们继续向上回溯会发现上游在最开始设置构造函数的参数args时设置的就是null,也就是说args的值需要向下探索。这里我们需要从autowireConstructor(beanName, mbd, ctors, args)这个入口向下求解,直到进入org.springframework.beans.factory.support.ConstructorResolver#autowireConstructor方法内部我们会发现一直找寻的args值出现了:

至此,BeanDefinition在创建对象实例中的使用基本已经分析完毕。

五、总结

不得不说,在阅读分析完BeanDefinition生成和使用的源码设计之后,以往对于Spring框架中Bean管理模块的功能理解才算真正意义上做到了一个闭环。当然这里的闭环并不是非常完美的闭环,因为这里我们只是简单的回答了Bean管理模块中关于Bean创建流程的相关问题,但是对于Bean管理模块是如何支撑Spring框架中诸如事务管理、MVC等其他模块的问题并没有做出相应的回答。这部分内容有兴趣的朋友可以先自行探索,也可以耐心等待笔者后续不知哪一天的更新(要学要写的东西太多,哈哈哈)。

本文在分析和讲解过程中大多只是展示了入口或者关键节点的代码,对于更细节的源码并没有贴出来,所以在学习的过程中最好能自己在结合源码进行debug来实际感受一下。

原文作者:Brucebat
链接:关于Spring的两三事:万物之始—BeanDefinition - 掘金

《spring设计思想》8-BeanDefinition中的beanClass从String转换为Class 上一节梳理了一下BeanDefinition的合并过程,而且讲到BeanDefinition中的基本属性 @Nullable private volatile Object beanClass; beanClass属性描述的是Bean的类型,而且很特殊的设置为Object类型,java中万物皆是对象,但是我们在读取xml或者propeties时,赋值的是什么类型呢,断点调试发现是Sting类型的对象, 但是在执行过getBean方法之后,会调用上一节的mergeBeanDefinition 阅读详情

相关推荐

从零到一:STM32G431的DSP库集成与FFT实战避坑指南

本文详细介绍了在STM32G431微控制器上集成CMSIS-DSP库并进行FFT实战开发的完整流程。重点解析了通过CubeMX和Keil环境配置DSP库的关键步骤、编译器宏定义陷阱及解决方案,并提供了FFT算法优化、内存管理及常见问题诊断的实用技巧,帮助开发者高效实现嵌入式信号处理应用。

oauth7security的博客 771

Spring源码之基于@ComponentScan生成BeanDefinition

注解中的提供的扫描路径加载Bean,扫描的核心方法是doScan()。本文用到的是Spring5.2.4版本的源码。

qq_42878176的博客 567

OpenV2X 车路协同开源平台 Columbia 版本正式发布!

OpenV2X车路协同开源平台Columbia 版本正式发布!

weixin_65571684的博客 1199

2.1、补充:ComponentsIndex和ScopedProxyMode

这里可以看到,我传入的basePackage和spring.components中配置的类的包名不一致,返回的就是false,这些类都不会在次生成BeanDefinition,因没有配置其他的basePackage,因此最终从Spring获取类的时候报错了。而代理对象执行时,执行的的是AOP逻辑,最重要的就是。在Spring中,如果想精确的控制Spring来扫描并生成那些类,可以在META-INF/spring.components文件中配置那些类是要交给Spring来管理的,其文件内格式是。

xsyl06的博客 368

SolidWorks2020详细步骤安装教程

1、在安装软件前请断开网络连接,需要安装.NETFramework3.5和4.0,最后还要确保把之前安装的旧版本完全卸载,以管理员身份运行SolidWorks_Flexnet_Server\server_remove.bat,然后等到服务“SolidWorksFlexnet服务器”将被删除。12、先不要运行软件,找到_SolidSQUAD_文件夹,将文件夹“ProgramFiles\SOLIDWORKSCorp”中的所有破解文件复制替到“ProgramFiles\SOLIDWORKSCorp”目录下;

qq_53545309的博客 1万+

Xilinx_JESD204B

Xilinx_JESD204B_AXI配置 说明:通过FPGA的高速数据接口JESD204B对AD9625进行高速采集。 环境:Vivado2018.3。 IP核:JESD204(7.2)。 参考手册:pg066_jesd204 v7.2。 资料以及IP_licence:JESD204B AXI协议资料:AXI 文章目录JESD204B概述JESD204B接口术语JESD204B 层JESD204B_AXI介绍AXI介绍JESD204B__AXI_Lite接口AXI-Lite接口介绍AXI-Lite接口信号

Crazzy_M的博客 1万+

mybatis源码分析

对于Java开发来说,mybatis对于我们是经常用到的,我们知道我们只要定义相应的接口,配置好扫包的路径,就会自动生成相关的接口实现代理类,那么mybatis是如何借助Spring完成这些操作的呢,在这里我就主要分享一下我在阅读了部分Mybatis源码后的一些总结 package com.xp.config; import com.xp.dao.XXX; import org.mybati...

lj872224的博客 300

yolov26改进 | 融合改进篇 | 基于 MobileNetV4 和双向特征金字塔网络BiFPN的融合改进(全网独家首发)

本文介绍BiFPN与MobileNetV4融合改进的YOLOv26。许多模块单独使用能够涨点,但直接叠加后可能因功能重复、通道不匹配、尺度冲突而掉点,因此融合前必须理解各模块作用。MobileNetV4利用UIB与Mobile MQA构建轻量主干,提升特征提取能力;BiFPN通过可学习权重完成双向多尺度融合,强化大、中、小目标的信息交互。两者优化Backbone与Neck,功能互补、结构冲突较少。本文提供代码、配置、消融对比及Codex修改思路,MobileNetV4也可替换其他主干,便于组合实验与二次创新

Snu77的博客 244

反射与代理+spring Bean

从反射和代理开始,学习spring bean的创建过程。

Feiyu883的博客 559

化工设备设计软件:PVELITE二次开发_(12).数据导入导出与兼容性

在数据导入之前,需要定义数据在PVELITE中的结构。可以通过编程接口定义字段名称和数据类型。# 导入必要的库 import pvelite # 创建PVELITE实例 pve = pvelite . PVELITE() # 定义CSV数据结构 csv_structure = {

kkchenjj的博客 1216

基于STM32设计的4G远程视频侦查小车(图传+远程控制+EMQX+MQTT)(204)

当前设计了一款基于STM32F103ZET6主控芯片和废旧Android手机改造的4G侦查小车。该设计充分利用已有的智能手机硬件资源,实现摄像头画面的实时采集与上传,以及远程控制功能。这样的设计不仅降低了成本,而且充分利用了废旧手机中高性能的硬件资源,如摄像头、4G通信模块和电池等,实现了资源的有效循环利用。

2536

全网最细致的spring源码分析(六):spring实例化策略

上一章节,实例化过程中反复提到实例化策略,这到底是做什么的呢?事实上,在经过前面的分析,我们已经得到了足够用于实例化的所有信息,完全可以使用最简单的反射方式直接构建实例对象,但spring却不仅仅如此。 spring初始化策略主要使用SimpleInstantiationStrategy类下的instantiate(RootBeanDefinition bd, @...

敲代码的旺财的博客 945

彻底讲透 SAP 中的 client-safe:从 CDS、AMDP 到 ABAP Cloud 的客户端隔离设计

SAP系统中的client-safe概念定义了技术边界:访问client-dependent数据的对象必须确保只看到单个client数据,而访问client-independent数据的对象则天然满足条件。这一原则直接影响CDS视图、AMDP等核心组件,并与ABAP Cloud开发模型紧密集成。在业务系统中,client isolation要求用户只能看到当前登录client的数据。SAP通过语言版本、对象规则和静态检查强制执行这一约束,特别是在ABAP Cloud开发中,AMDP方法和发布的API必须满足

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 3269

【Spring】Bean和BeanDefinition

先来看看java的Class,这个是大家最熟悉的,站在面向对象的角度,万物皆对象,而Class就是用来描述对象的对象。 /* * Private constructor. Only the Java Virtual Machine creates Class objects. * This constructor is not used and prevents the def...

hansirl的博客 259

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

spring源码之浅析BeanDefinition

上一章说,想要模拟完成Mybatis的Mapper自动注入,而这个自动注入使用了BeanDefinition,所以我们要先了解一下这个东西。才能看懂下一章的代码。 简而言之的话,是Bean的建模对象。 对Java有了解的话,一定都知道一句话叫做:万物皆对象。 那么对于java来说,Bean也是一个对象,既然是对象,那么就肯定可以抽象出来,通过一定的结构进行存储。那么这个抽象出来的结构就是BeanDefinition。 BeanDefinition里面记录了Bean对象的所有的属性,比如构造方法、构造方法参数

weixin_41011482的博客 227

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

spring生命周期七个过程_想要学会Spring源码,你必知必会的BeanDefinition原理!

作者:止术出自:OSCHINA原文:my.oschina.net/u/4600853/blog/4556323一、BeanDefinition浅析1. 基本概念了解首先我提出一个问题:一个java对象和一个Spring Bean有什么区别?这是一个经典的面试题,什么是java Object?万物皆对象,在Java内部所有的类,经过创建之后都可以称之为一个对象,SpringBean也是一个java ...

weixin_39603908的博客 1784

android 蓝牙通讯demo

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

想要学会Spring源码,你必知必会的BeanDefinition原理!

一、BeanDefinition浅析 1. 基本概念了解 首先我提出一个问题:一个java对象和一个Spring Bean有什么区别? 这是一个经典的面试题,什么是java Object?万物皆对象,在Java内部所有的类,经过创建之后都可以称之为一个对象,SpringBean也是一个java Object, 但是Spring Bean是脱离于JAVA Object的,为什么这么说呢?因为一个class要想变成对象只需要new一下,就能够称之为一个对象,但是一个类要想变成一个Spring Bean就需要经过

皇甫嗷嗷叫 451

Spring的Bean创建过程

spring将内部管理的诸多对象称为一个个bean,而这些bean的创建流程大致分为两个大阶段: 下面本人将从上述两个阶段来阐述bean的完整创建过程。 在对象进行创建之前,spring容器需要了解所创建的对象的信息,才能在后续阶段根据了解的信息创建bean对象。这些信息即是实际工作中我们为对象所写的配置信息,它们一般以xml文件、properties文件和注解的形式存在于我们的项目之中。 一个以xml文件为存储形式的bean配置文件如下: 因此,

Yuan_Su_的博客 2951

Spring学习--IOC容器的初始化过程

IOC容器初始化概述 IOC容器初始化是由refresh()

m0_47954009的博客 2292

Spring基础(1):两个概念

上帝说,要有光。于是特斯拉搞出了交流电。Java说,万物皆对象。但是Spring另外搞了BeanDefinition...什么BeanDefinition呢?其实它是bean定义的一个顶级接口:正如BeanDefinition接口的注释所言:一个BeanDefinition是用来描述一个bean实例的哎呀卧槽,啥玩意啊。描述一个bean实例?我咋想起了Class类呢。其实,两者并没有矛盾。

smart_an的专栏 727

轻松理解Spring

前言 这篇文章在前一段时间看到一位大佬写的,因为写的逻辑清晰、通俗易懂,当时我就整理了一下笔记,希望日后自己也行写出这样的文章。如果想对spring了解和入门的同学,相信认真阅读了本篇文章定会收获颇丰。 特此说明:此篇文章主要目的是当做范文,以此鼓励自己在不断学习总结中创作出更多更好的优质原创文章;找了半天没有找到原文章,如有打扰即刻删除。 主要内容: 默认题主说的Spring是Spring fr...

weixin_38170829的博客 277

spring 源码系列(四)spring中的重要类介绍

目录 一、BeanDefinition 二、BeanFactory和FactoryBean BeanFactory FactoryBean 三、BeanFactoryPostProcessor BeanDefinitionRegistryPostProcessor 四、BeanPostProcessor 总结 spring源码非常负责,如果想阅读好spring源码,那么一些重要类...

linhui258的博客 1380

怎么回答面试官:你对Spring的理解?

作者:bravo1988 链接:https://www.zhihu.com/question/48427693/answer/723146648 来源:知乎 最近看了点Spring的源码,正好来稍微扯一扯,帮一部分培训班的朋友撕开一道口子,透透气。我自己都是看的培训班视频,所以也算培训班出身吧。所以下文开口闭口“培训班”,不要觉得是我在贬低培训班,完全没有。 (默认题主说的Spring是Spr...

芒果不是程序猿v: 的博客 457

spring 切片打日志_Spring基础(1):两个概念

最近看了点Spring的源码,于是来稍微扯一扯,希望能帮一部分培训班出身的朋友撕开一道口子,透透气。广义上的Spring指的是Spring整个项目,包含SpringBoot、SpringCloud、SpringFramework、SpringData等等,本系列文章只讨论狭义上的Spring,也就是SpringFrameWork。主要内容:盲点Spring说,万物皆可定义默默付出的后置处理器利用后...

weixin_30923925的博客 111

面试官:Spring的Bean实例化过程应该是怎样的?

对于写Java的程序员来说,Spring已经成为了目前最流行的第三方开源框架之一,在我们充分享受Spring IOC容器带来的红利的同时,我们也应该考虑一下Spring这个大工厂是如何将一个个的Bean生产出来的,本期我们就一起来讨论一下Spring中Bean的实例化过程。这里我们并不会详细的分析源代码,只是给出Spring在完成哪些工作的时候使用到了什么类,这些类具体的职责都是什么,如果我们要弄...

十指波课堂的博客 682

Spring核心容器实现之容器初始化

体系设计1,BeanFactory:Bean工厂 为IOC容器管理对象间依赖关系提供基础服务。 顶层接口:BeanFactory,定义IOC容器基本功能规范, 第二层接口:ListableBeanFactory-可列表Bean、HierarchicalBeanFactory -继承关系Bean、AutowireCapableBeanFactory - 自动装配...

Munger6的博客 450
上一篇: Alibaba永远滴神,阿里内部最新Java基础到中高级核心面试手册
下一篇: SpringBoot2.x 自动化生成代码整合Mybatis
Java技术那些事儿
博客等级 码龄5年 2306粉丝 2584原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值