前言
我们很多时候在阅读源码之前对源码的大体结构没有一个认识,导致在看源码的时候迷失在各个代码的细节里。这篇文章试着介绍一下spring源码的大体框架。让我们能在框架里面进一步认识spring源码。
介绍
IOC 和AOP 的关系
说起spring源码我们都会想到AOP 和IOC ,IOC 实际上就是spring 构造一个容器,将各个bean 对象初始化到这个容器的过程。AOP 是IOC的构建容器中bean的一小步,这里主要介绍关于IOC构建容器和bean 中的过程。
实例化和初始化
在开始这个IOC 构建容器和Bean的过程中首先需要先认识 实例化 和 初始化,实例化在堆中
堆中开辟一块默认空间,属性都是默认值。初始化则是填充属性,赋值和调用初始化方法
IOC 构建容器和Bean的过程
我们可以大致分为下面几步:
1、我们将yml 和properties ,yml 通过一套统一的规范(BeanDefinitionReader)将Bean 解析成 Bean的定义信息BeanDefinition。
2、这个时候BeanDefinition 在实例化之前,提供一个BeanFactoryPostProcessor 的接口来对BeanDefinition的定义进行修改。在BeanFactory标准初始化之后调用,这时所有的bean定义已经保存加载到beanFactory,但是bean的实例还未创建。可以用来来定制和修改BeanFactory的内容,如覆盖或添加属性。
3、这个时候将定义好对象通过反射实例化对象,这个时候Bean 就是 处于实例化中的。
4、这个时候实例化bean 属性还没有设置,紧接着就是填充属性、初始化Bean等init等操作、完整bean对象的过程。
5、在这个过程中 BeanPostProcessor 有一个这样的接口,有两个方法在 初始化Bean等init等操作 前后调用,这也是AOP 处理的地方。
AbstractApplicationContext#refresh源码
这里之所以将这一段贴出来主要是因为,pplicationContext作为Spring上下文的关键接口,除了BeanFactory的功能,还包括各种环境、参数、BeanFactoryPostProcessors后处理器、事件以及单例bean的初始化等一系列操作,其中以refresh方法为spring启动入口。
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
//刷新前的预处理;
prepareRefresh();
//获取BeanFactory;默认实现是DefaultListableBeanFactory,在创建容器的时候创建的
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
//BeanFactory的预准备工作(BeanFactory进行一些设置,比如context的类加载器,BeanPostProcessor和XXXAware自动装配等)
prepareBeanFactory(beanFactory);
try {
//BeanFactory准备工作完成后进行的后置处理工作
postProcessBeanFactory(beanFactory);
//执行BeanFactoryPostProcessor的方法;
invokeBeanFactoryPostProcessors(beanFactory);
//注册BeanPostProcessor(Bean的后置处理器),在创建bean的前后等执行
registerBeanPostProcessors(beanFactory);
//初始化MessageSource组件(做国际化功能;消息绑定,消息解析);
initMessageSource();
//初始化事件派发器
initApplicationEventMulticaster();
//子类重写这个方法,在容器刷新的时候可以自定义逻辑;如创建Tomcat,Jetty等WEB服务器
onRefresh();
//注册应用的监听器。就是注册实现了ApplicationListener接口的监听器bean,这些监听器是注册到ApplicationEventMulticaster中的
registerListeners();
//初始化所有剩下的非懒加载的单例bean
finishBeanFactoryInitialization(beanFactory);
//完成context的刷新。主要是调用LifecycleProcessor的onRefresh()方法,并且发布事件(ContextRefreshedEvent)
finishRefresh();
}
......
}