SpringIOC源码

BeanFactory创建流程

获取BeanFactory

BeanFactory是spring框架中IOC容器的顶层接口,只是用来定义一些基础功能,定义一些基础规范,而ApplicationContext是它的一个子接口,所以ApplicationContext是具备BeanFactory提供的全部功能。
BeanFactory为SpringIOC的基础容器,ApplicationContext是容器的高级接口,拥有更多的功能,比如说国际化支持和资源访问(xml,java配置类)等。

启动IOC容器的方式:
1)Java环境下启动IoC容器
·ClassPathXmlApplicationContext:从类的根路径下加载配置⽂件(推荐使⽤)
·FileSystemXmlApplicationContext:从磁盘路径上加载配置⽂件
·AnnotationConfigApplicationContext:纯注解模式下启动Spring容器
2)web环境下启动IOC容器
从xml启动容器
在这里插入图片描述
从配置类启动容器:
在这里插入图片描述
在这里插入图片描述

这里我们采用SpringIOC纯xml模式先定义一个applicationContext.xml配置bean相关信息

<?xml version="1.0" encoding="UTF-8"?>
 <beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"    
  xsi:schemaLocation="http://www.springframework.org/schema/beans
  https://www.springframework.org/schema/beans/spring-beans.xsd ">  
  <bean id="lagouBean" class="com.lagou.LagouBean"/>  
  <bean id="myBeanFactoryPostProcessor" class="com.lagou.MyBeanFactoryPostProcessor"/>  
  <bean id="beanTest" class="com.test.BeanTest"/> </beans>

创建com.test包,创建BeanTest类,定义id和name。
接下来在test包下,创建测试类,写测试方法如下:

@Test
 public void testIoC() {
   ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:applicationContext.xml"); 
   BeanTest beanTest = applicationContext.getBean(BeanTest.class);
   System.out.println(beanTest );
 }

接下来通过源码看IOC的初始化流程。根据断点调试,发现在未设置延迟加载的前提下,bean的创建是在容器初始化过程中完成的。
进入构造器中:
进入构造器中
核心refresh方法核心refresh方法
首先刷新前的预处理(不重点关注),重点红色框方法,功能:获取beanFactory,默认实现DefaultListableBeanFactory,加载BeanDefinition并注册到BeanDefitionRegistry 首先刷新前的预处理
在这里插入图片描述
实例化DefaultListableBeanFactory,设置序列化id,自定义bean工厂的一些属性(是否覆盖、是否允许循环依赖),加载BeanDefinition
在这里插入图片描述
创建的时候DefaultListableBeanFactory中的部分定义
在这里插入图片描述

BeanDefinition加载解析及注册

进入到AbstractXmlApplicationContext类的loadBeanDefitions方法 并依次按着箭头走进入相应的loadBeanDefitions方法​ , AbstractXmlApplicationContext ​ —> AbstractBeanDefinitionReader —> XmlBeanDefinitionReader ​ 一直执行到XmlBeanDefinitionReader 的doLoadBeanDefinitions 方法
在这里插入图片描述
resource定位:对BeanDefinitions资源定位过程,就是找到定义Javabean信息的xml文件,并封装成Resource对象
在这里插入图片描述
在这里插入图片描述

读取xml信息,将xml信息保存到document对象,并解析对象封装BeanDefinition并进行注册
在这里插入图片描述
重点关注XmlBeanDefinitionReader 的registerBeanDefinitions 方法,期间产生了多次重载调用,选择最后一个
在这里插入图片描述
来到DefaultBeanDefinitionDocumentReader类中的registerBeanDefinitions
在这里插入图片描述

进入doRegisterBeanDefinitions
在这里插入图片描述

BeanDefinitionParserDelegate中创建好的delegate
在这里插入图片描述
重点是parseBeanDefinitions ,它的前后两个方法都是钩子方法

在这里插入图片描述

重点进入parseDefaultElement ,解析bean元素,进入到具体处理方法processBeanDefinition

在这里插入图片描述

解析成BeanDefinitionHolder对象,try里完成注册
在这里插入图片描述
在这里插入图片描述

返回defaultBeanDefinitionDocumentReader继续执行
在这里插入图片描述
在这里插入图片描述
BeanDefinitionReaderUtils
在这里插入图片描述
DefaultListableBeanFactory
在这里插入图片描述

注册就是把xml中定义的bean信息封装为BeanDefinition对象放入一个map中
在这里插入图片描述
在这里插入图片描述

至此已经完成BeanDefinition的加载解析及注册子流程

Bean创建流程

接着看下bean的创建流程。
首先分析存放bean信息的map集合,发现在DefaultListableBeanFactory类中有doGetBeanNameForType方法中用到。看到主要的代码为isTypeMatch这个方法。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

通过断点查看当前singletonObjects存放的是实例化之后的Bean对象,此时为null, 通过这个关键字,查找singletonObjects什么时候不为空的,在AbstractAutowireCapableBeanFactory类中有put的过程,在此打断点,然后分析调用栈。
在这里插入图片描述
在这里插入图片描述

发现最终bean的创建是在AbstractApplicationContext#refresh() 的finishBeanFactoryInitialization方法,这个方法功能有初始化所有剩下的非懒加载的单例bean,初始化创建非懒加载方法的单例bean实例(未设置属性)----填充属性,初始化方法调用(比如调用afterPropertiesSet、init-method方法),调用BeanPostProcessor(后置处理器)对bean进行处理。

通过断点发现红色框部分代码就是实例化所有立即加载的单例bean。
在这里插入图片描述
红色框就是实例化bean的方法,注意如果是懒加载 情况下不会去getBean,
继续进⼊DefaultListableBeanFactory类的preInstantiateSingletons⽅法(实例化所有立即加载的单例bean),我们找到下⾯部分的代码,看到⼯⼚Bean或者普通Bean,最终都是通过getBean的⽅法获取实例

在这里插入图片描述

AbstractBeanFactory类中createBean继续追踪在这里插入图片描述

AbstractAutowireCapableBeanFactory类中,重点关注两个方法一个是下面红色框已经创建bean实例,但是未设置属性。
在这里插入图片描述

第二是Bean属性填充,调用初始化方法,应用BeanPostProcessor后置处理器
在这里插入图片描述
进入initializeBean方法:
在这里插入图片描述
然后invokeInitMethods中
在这里插入图片描述
在这里插入图片描述

通过代码可以总结出bean的生命周期
在这里插入图片描述

lazy-init延迟加载机制

普通bean的初始化是在容器启动初始化阶段执行的,而被lazy-init=true修饰的bean,是在容器里第一次getBean时进行触发。spring启动的时候会把所有的bean信息解析转化成Spring能够识别的BeanDefinition并存入到map集合供初始化时用,然后对每个BeanDefinition进行处理,如果是懒加载则初始化阶段不处理,其他的在容器初始化阶段进行初始化并依赖注入。
看一下getBean的源码:
DefaultListableBeanFactory类中一直断点
在这里插入图片描述

直到进入AbstractBeanFactory类的doGetBean,此时如果不是懒加载会直接得到bean,如果是懒加载则得不到继续往下走
在这里插入图片描述

这里就会创建bean然后得到实例
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值