首页 > 编程语言 >Spring源码学习笔记6——Spring bean的实例化

Spring源码学习笔记6——Spring bean的实例化

时间:2022-08-21 11:33:32浏览次数:49  
标签:初始化 实例 Spring Bean bean 源码 单例

一丶前言

前面我们了解到读取xml or 根据扫描路径生成BeanDefinition并注册到BeanFactory,相当于我们具备了生火做饭的原材料:BeanDefinition,接下来就是Spring最为核心的,根据BeanDefinition实例化Bean,并且对Bean的属性进行依赖注入

image-20220601203530779

其中Spring给了我们众多的扩展点,也涉及到面试常问的点——循环依赖的问题,本章我们探讨较为简单的内容——Spring怎么实例化一个Bean,根据JavaSE知识,我们知道实例化一个Bean 可以通过new or 反射的方式,Spring也不外呼这两种方式

二丶源码学习的简单例子

image-20220601204246710

image-20220601204318299

这里我就定义了两个类,模拟工作中最常见的场景

debug 入口

image-20220601204436867

image-20220601204813228

三丶Bean的实例化

完成BeanFactory 所有Bean的实例化和初始化,是DefaultListableBeanFactory的preInstantiateSingletons方法进行处理的,首先会获取所有Bean的名称,循环处理每一个BeanDefinition

image-20220601205615533

可以看到Spring只会先初始化非抽象,且是单例,且非懒加载的Bean,且对FactoryBean存在特殊处理,这里对FactoryBean按下不表,接下来Bean的实例化和初始化是调用getBean(bean名称)进行实例化和初始化的,getBean方法实际就是直接调用doGetBean方法的

1.构造bean的前置操作

image-20220601220715515

1.1获取bean的名称

image-20220601220017348

1.2从单例池中获取bean对象

image-20220601220354254

singletonObjects被称为一级缓存 是一个ConcurrentHashMap key是bean的名称 value是bean的示例
注意上面的方法,如果单例池中有那么也不会进入if 直接返回了
这就是为什么单例只会创建一次,只存在一个实例

1.3标记当前bean已经创建

image-20220601220954595

其实为什么还没有创建就标记为创建了,我不是很理解

2.加载当前bean 依赖的bean

image-20220601221344504

3.处理单例bean

image-20220601221916382

image-20220601222301987
注意这里的addSingletion 我标注了注册到单例池,但是不仅仅是注册到单例池,这和spring的循环依赖密切相关,后续循环依赖分析的时候进行详细学习

我们可以发现这个getSingleton方法,功能是,如果当前bean在单例池没有,那么调用ObjectFactory的getObject方法获取,在外层其实调用了createBean方法,让我们来看看createBean

3.1createBean

这个方法其实是在AbstractAutowireCapableBeanFactory中实现( DefaultListableBeanFactory的父类)AbstractAutowireCapableBeanFactory的定位是一个提供 bean 创建(使用构造函数解析)、属性填充、和初始化的BeanFactory

3.1.1实例化bean的前置操作

image-20220601223421408

我们重点看下这个resolveBeforeInstantiation 方法这是spring给我们的一个扩展点

image-20220601223813817

  • InstantiationAwareBeanPostProcessor 具备实例化感知能力的bean后置处理器

这里关注下postProcessBeforeInstantiation 和 postProcessAfterInitialization 方法

注意Instantiation 和 Initialization 的区别,前者是实例化(反射生成bean对象,任何属性都没有赋值,生成对象叫实例化)后者是初始化(属性赋值,初始化方法调用叫初始化)

image-20220601224404292

  • applyBeanPostProcessorsBeforeInstantiation 提供我们自己定一个bean,而不是spring帮我们反射生成bean的扩展,后续spring不会帮我们进行依赖注入

image-20220601225017654

  • applyBeanPostProcessorsAfterInitialization 提供对bean进行代理的扩展

image-20220601225218640

3.2doCreateBean

如果前面的InstantiationAwareBeanPostProcessor 没有返回一个bean 那么接下来就是spring容器为我们生成这个bean

image-20220601233452824

image-20220601233639847

这里的策略是CglibSubclassingInstantiationStrategy,提供普通的构造方法反射方式和CGLIB两种方式

image-20220601234029225

  1. 构造方法反射生成

    image-20220601234402603

  2. CGLIB

    image-20220601234707212

    具体怎么实现lookup和methodRepalcer的,后续学习一下cglib

4.回调MergedBeanDefinitionPostProcessor#postProcessMergedBeanDefinition

image-20220601235404916

所有的MergedBeanDefinitionPostProcessor 调用其postProcessMergedBeanDefinition 方法,

回调 postProcessMergedBeanDefinition 方法时,已经拿到了 merged bean definition,并且还未开始 poplateBean 填充 bean 属性、
initlializeBean 初始化 bean 对象,
因此可以在这里对 merged bean definition 进行一些操作
,在 poplateBean 或 initlializeBean 阶段使用前面操作结果实现所需功能

@PostConstruct,@PreInit @Resouce,@Autowired 
@InitMethod 都在这里实现的
具体如何实现的,后续的源码学习笔记再进行总结

5.提前暴露对象

spring解决循环依赖的重点步骤
如何解决循环依赖的,后续的源码学习笔记再进行总结

image-20220601235832983

addSingletonFactory 会向singletonFactories put一条记录

singletonFactories key是bean名称 value 是ObjectFactory

标签:初始化,实例,Spring,Bean,bean,源码,单例
From: https://www.cnblogs.com/cuzzz/p/16609681.html

相关文章

  • SpringBoot框架:配置项目在访问后台端口时默认跳转的接口或页面
    一、配置一般需要这种配置的都是前后端一体的项目,在通过后台端口访问时需要默认跳转到某个指定的接口,或者跳转到某个执行的接口。实现WebMvcConfigurer接口,重写a......
  • Tomcat源码分析--类加载器
    Tomcat类加载器结构上图是Tomcat文档中所展示的Tomcat类加载结构。在这个结构中Bootstartap和System的类加载器由java虚拟机实现。common类加载器由Tomcat容器实现,它对......
  • 第一个Spring Boot项目
    上一节学习了通过Spring官网创建SpringBoot项目,导入了一个demo项目,但是没有写代码运行,这一节就来学习一下怎么运行。1、首先在demo文件夹下创建一个controller包,再创建一......
  • SpringBoot--嵌入式Servlet容器
    一、嵌入式Servlet容器在传统的Web开发中,需要将项目打成war包,在外部配置部署好Tomcat服务器,而这个Tomcat就是Servlet容器,在使用SpringBoot开发时,我们无需再外部......
  • Spring 04: IOC控制反转 + DI依赖注入
    Spring中的IOC一种思想,两种实现方式IOC(InversionofControl):控制反转,是一种概念和思想,指由Spring容器完成对象创建和依赖注入核心业务:(a)对象的创建(b)依赖的......
  • SpringBoot--静态资源映射处理
    在web开发中,静态资源的访问是必不可少的,如图片、js、css等资源的访问SpringBoot对静态资源访问提供了很好的支持,基本使用默认配置就能满足开发需求(嵌入式servlet容器)先......
  • Vulfocus靶场 | spring 代码执行 (CVE-2018-1273)
    漏洞描述SpringData是一个用于简化数据库访问,并支持云服务的开源框架,SpringDataCommons是SpringData下所有子项目共享的基础框架。SpringDataCommons在2.0.5及以......
  • springMvc32-原生apiSpring MVC过滤器-HiddenHttpMethodFilter
    浏览器form表单只支持GET与POST请求,而DELETE、PUT等method并不支持,spring3.0添加了一个过滤器,可以将这些请求转换为标准的http方法,使得支持GET、POST、PUT与DELETE请求,该过......
  • springMvc33-estful的delete
    创建maven项目就不说了,需要的找我前面的博客pom.xml文件   <projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-ins......
  • springMvc34-restful的put
    创建maven项目就不说了,需要的找我前面的博客pom.xml文件   <projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-ins......