SpringIoC容器的源码解析

源码也看了好几遍了,但是就是记不住,所以又来缕缕。

IOC现在是一个框架都具备了,虽然在自己也实现了一个简单的 框架,也具备IOC的功能,但是还是太简单了。下面来看看Spring的IOC到到底是个什么情况。
初始化容器一般用两种方式,从xml文件读取,从配置类解析。分别对应于以下代码。

  ApplicationContext applicationContext = new FileSystemXmlApplicationContext(xmlPath);
//Entrance.class 你的配置类,被@Configuration标记
  ApplicationContext applicationContext =  new AnnotationConfigApplicationContext(Entrance.class);

通过

String[] names = applicationContext.getBeanDefinitionNames();
        for (String name : names) {
            System.out.println(name);
        }

可以输出容器初始化了哪些Bean.
在这里插入图片描述
可以看到容器的初始化,除了我们自己的打上了注解的类,还有一些Spring自己的类。

Spring框架虽然负责,总体来说IOC可以概括为3个步骤。
1.解析配置
2.定位和注册兑现对象
3.注入对象

预备知识

在JAVA中,通过类.classs对象,或者对象.getClass()获取 该对象的描述,简而言之
class对象就是描述这个对象“我是谁的问题”。
在Spring中,Bean的概念对应于Java的对象,但是因为Spring需要做更多额外的事情,Spring通过BeanDefinition来描述Bean。对应于JAVA用CLASS来描述对象。回答我是谁的问题。

BeanDefinition的属性我们经常用到,只是不知道我们其实在使用而已。
他的常用属性:

  • 懒加载 作用范围(单例,多例)
  • 别名
  • 优先级(当多个类型共同竞争的时候的参考优先使用这个)
  • 工厂方法
  • 工厂类
    等等

不管是xml配置还是注解类配置,最终都会被框架解析成 一个个的BeanDefiniton注册在容器中。
最后 容器才根据BeanDefinition的指示来初始化Bean.
在这里插入图片描述

BeanDefiniton家族

在这里插入图片描述
BeanDefiniton也是有parent属性的,最后的Definition会综合各个层级统一生成定义。
Java里面是通过集成声明父子关系,而Spring是通过属性设置的。

BeanFactory

Spring的设计完全遵循了单一职责,每个接口提供一个能力。所以看源码的时候 ,各种分支特别多。
BeanFactory是简单容器,提供了一些容器常用的功能。主要面向Spring自己使用或者是基础设施。
我们正真用到的是ApplicationContext.
下图就是BeanFactory申明的方法。在这里插入图片描述
在这里插入图片描述

ApplicationContext

public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory,
		MessageSource, ApplicationEventPublisher, ResourcePatternResolver 

EnvironmentCapable:获取配置环境信息
ListableBeanFactory:可以列表的形式管理容器类的BeanDeFinition
HierarchicalBeanFactory 容器可以设置父容器
MessageSource:国际化接口
** ApplicationEventPublisher**事件发布
ResourcePatternResolver资源解析器
在这里插入图片描述

注解配置的加载和解析注册

以调式的方式启动。

  ApplicationContext applicationContext =  new AnnotationConfigApplicationContext(Entrance.class);

因为Spring默认使用的就是DefaultListableBeanFactory,容器 的初始化必然要注册BeanDefinition,所以提前在registerBeanDefinition打上断点。
在这里插入图片描述
最开始出现的BeanDefinition并不是 我们熟悉的类,因为 初始化之前还要注册一些系统自带的BeanDefinition。
在这里插入图片描述
栈1:启动类调用在这里插入图片描述
栈2:注册BeanDefinition的读取类,组件扫描器。
在这里插入图片描述
此时也顺便初始化了DefaultListAbleBeanFactory.
在这里插入图片描述
可以得出结论 ,注解类启动方式最开始启动的时候,会注册BeanDefinitionrReader,和一个 默认的容器 。
然后继续RESUME,直到出现用户的类。
在这里插入图片描述
后面我直接文字说明了。
读取到配置类,执行注册配置类的逻辑。具体是解析配置类的注解相关信息,然后利用动态代理生成一个 BeanDefinitin注册到容器。
在这里插入图片描述
继续调式,看看普通的业务Bean是怎么注册的。

在这里插入图片描述
到refresh方法,可以看到 普通的业务类是在Refresh的时候才注册的。
在这里插入图片描述
更进一步,发现是在容器的后置处理器时候进行普通Bean的注册。
但是在处理容器的后置处理器时,要优先判断是否有Bedefinition的后置处理器 ,如果有,要限制行。
最后才将BeanDefnition注册到容器中。
我在后面发现一个疑问,为什么每次解析普通类的时候,都要

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值