Spring 源码 -- Spring 初始化
本文最后更新于:4 个月前
⚡入口代码
package ind;
import ind.config.SpringConfig;
import ind.dao.TestDao;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* @author yinchao
*/
public class Main {
public static void main (String[] args) {
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
/* refresh 方法用于初始化 Spring 容器 */
annotationConfigApplicationContext.refresh();
TestDao bean = annotationConfigApplicationContext.getBean(TestDao.class);
bean.query();
}
}
⚡调用链
-
AnnotationConfigApplicationContext
这个类就完成了 Spring 的初始化
-
先执行他的父类 GenericApplicationContext 的构造方法
这个类是 Spring 上下文的环境
-
构造函数中一个成员变量 DefaultListableBeanFactory 被初始化
这个类是 Spring 的 Bean 工厂,里面有很多生成 Bean 所需要的原料
例如:用于存放 BeanName 和 BeanDefinition [1] 的 beanDefinitionMap
按照 Beam 的注册顺序组合的 BeanName 的 list
其他成员不一一列举 …
-
-
继续在 AnnotationConfigApplicationContext 构造函数中有一个成员 AnnotatedBeanDefinitionReader 开始初始化
这个 reader 的作用就是作为一个注册器来向 Spring 注册一个 bean
可以根据上图的 AnnotationConfigApplicationContext3 中看到,new AnnotatedBeanDefinitionReader(BeanDefinitionRegistry) 传入的参数是
this
,即这个 AnnotationConfigApplicationContext 就是一个 BeanDefinitionRegistry,也可以通过图片 AnnotationConfigApplicationContext1 看到这个类本来就实现了 AnnotationConfigRegistry 接口 。-
构造继续委托到 AnnotationConfigUtils 的 registerAnnotationConfigProcessors 方法
-
-
AnnotationConfigApplicationContext 构造函数中另一个成员 ClassPathBeanDefinitionScanner 开始初始化
他能够扫描 BeanDefinition,能够扫描一个类或者包,并且转换成BeanDefinition
-
-
AnnotationConfigApplicationContext 构造函数结束,完成类初始化之后,调用 register 方法
进一步调用
-
AnnotationConfigApplicationContext 调用 refresh() 方法
这个方法主要是准备好 Bean 工厂,并实例化 Bean 对象
-
prepareBeanFactory() 方法
最后的 addBeanPostProcessor 方法只是把一个 BeanPostProcessor 实例加入到 BeanFactory 里面维护的一个 BeanPostProcessor 后置处理器 list 列表中
在 Bean 的实例化过程中会依次循环调用这个 list 中的 BeanPostProcessor 对象的方法
-
invokeBeanFactoryPostProcessors() 方法
-
最后循环调用接口的实现类的接口重写方法,例如对于 ConfigurationClassPostProcessor 类:
主要函数逻辑:
-
checkConfigurationClassCandidate 方法
-
isLiteConfigurationCandidate 方法
-
又是一个空壳 parse 函数调用
被调函数:
-
继续调用 doProcessConfigurationClass 方法实现主要逻辑
-
parse 方法处理 @ComponentScan 注解的属性信息,例如 basePackage 等
-
doScan()
-
findCandidateComponents 方法又调用 scanCandidateComponents,而这个方法最后实现了扫描 Bean 的主要逻辑,可以自己模拟一遍,此处不特别展示
-
其中调用的 registerBeanDefinition() 就是 BeanDefinitionReaderUtils 的 registerBeanDefinition 方法 (之前分析过),将 Bean 加入到工厂里面
-
-
-
-
-
-
-
附录: Spring 扩展点[2]
BeanDefinition: 是用于描述 Bean 的类。例如我们用 User.java (userName,password …) 是现实世界中对
用户
这个对象的抽象描述,而用 Class.java 来描述各种各样的 Java 类 (name,classLoader,useCaches …),同理, BeanDefinition (isPrimary,isLazyInit,getFactoryBeanName …) 就是用来描述交给 Spring 管理的 Bean。 ↩︎Spring 扩展点:
- BeanPostProcessor
- BeanFactoryPostProcessor
- BeanDefinitionRegistryPostProcessor
- FactoryBean
本博客所有文章除特别声明外,均采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 。转载请注明出处!