Spring的启动过程
前言
前文中已构建好源码阅读环境,也成功搭建一个demo项目,这次就开始探究Spring启动过程。
正文
Spring IoC的容器体系
IoC容器是Spring的核心模块,是抽象了对象管理、依赖关系管理的框架解决方案。Spring 提供了很多的容器,其中 BeanFactory 是顶层容器(根容器),不能被实例化,它定义了所有 IoC 容器 必须遵从的一套原则,具体的容器实现可以增加额外的功能,比如我们常用到的ApplicationContext,其下更具体的实现如 ClassPathXmlApplicationContext 包含了解析 xml 等一系列的内容,AnnotationConfigApplicationContext 则是包含了注解解析等一系列的内容。Spring IoC 容器继承体系,需要使用哪个层次用哪个层次即可,不必使用功完全的。
BeanFactory 顶级接口方法栈如下
BeanFactory 容器继承体系
通过其接⼝设计,我们可以看到我们⼀贯使⽤的 ApplicationContext 除了继承BeanFactory的⼦接⼝,还继承了ResourceLoader、MessageSource等接⼝,因此其提供的功能也就更丰富了。
Bean生命周期关键时机点
思路是自己创建个bean,并分别在接口实现的构造器、接口方法中
断点,观察线程调用栈,分析出 Bean 对象创建和管理关键点的触发时机。
启动程序打上断点后,debug运行程序
# debug
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(AppConfig.class);
# 执行父类的静态代码块,获取上下文关闭事件的类名
static {
// Eagerly load the ContextClosedEvent class to avoid weird classloader issues
// on application shutdown in WebLogic 8.1. (Reported by Dustin Woods.)
ContextClosedEvent.class.getName();
}
# 调用构造方法
public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
// 默认构造方法
this();
// 注册,参数就是传入的参数,appConfig.class
register(componentClasses);
// 刷新
refresh();
}
接下来看下,this();
方法做了什么。
/**
* Create a new AnnotationConfigApplicationContext that needs to be populated
* through {@link #register} calls and then manually {@linkplain #refresh refreshed}.
*/
public AnnotationConfigApplicationContext() {
// 实例化BeanDefinition 的阅读器,用途解析BeanDefinition
this.reader = new AnnotatedBeanDefinitionReader(this);
// 实例化BeanDefinition 的扫描器,用途扫描需要创建的bean
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
然后调用 register(componentClasses);
方法将参数appConfig注入到BeanDefinitionMap 中。简单介绍一下
BeanDefinition, 这个类用来描述bean信息,记载了一个类的所有信息。往内深挖一下,看做了哪些操作。
debug一直往里走,看到根据参数循注册方法的调用。
public void register(Class<?>... componentClasses) {
for (Class<?> componentClass : componentClasses) {
registerBean(componentClass);
}
}
继续往里走,最终会调用
<T> void doRegisterBean(Class<T> beanClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
// 实例化一个入参beanClass的BeanDefinition
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
// 根据原数据判断是否需要跳过下面赋值操作
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
abd.setInstanceSupplier(instanceSupplier);
// 获取原型,判断是单例还是多例
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
// 是否有其他名称
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
// 所有BeanDefinition的通用操作,给BeanDefinition属性赋值,是否懒加载,私有,依赖检查等
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
if (qualifiers != null) {
for (Class<? extends Annotation> qualifier : qualifiers) {
if (Primary.class == qualifier) {
abd.setPrimary(true);
}
else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
}
else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
// 是否有用户自定义的BeanDefinition扩展,有进行用户自定义的扩展
for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
customizer.customize(abd);
}
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
// 这一步判断是否需要做AOP代理
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
// 注入到beanDefinitionMap中
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
这个方法调用完成后,看到beanFactory中的beanDefinitionMap已经注入了6个beanDefinition,其中前五个是spring的RootBeanDefinition,是自己程序运行所必要的信息,后面就是根据入参appconfig而生成的beanDefinition。
在上个方法中,笔者讲到了对beanDefinition的一些通用操作方法,简单的挖一下这个方法
// 所有BeanDefinition的通用操作,给BeanDefinition属性赋值,是否懒加载,关键,依赖检查等
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
// 调用processCommonDefinitionAnnotations方法
public static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd) {
processCommonDefinitionAnnotations(abd, abd.getMetadata());
}
// 根据注解类型来赋值
static void processCommonDefinitionAnnotations(AnnotatedBeanDefinition abd, AnnotatedTypeMetadata metadata) {
// 解析元数据中是否有@Lazy的注解如果类上使用了@Lazy注解,值为true
AnnotationAttributes lazy = attributesFor(metadata, Lazy.class);
if (lazy != null) {
abd.setLazyInit(lazy.getBoolean("value"));
}
// 只截取部分代码
}
后话
以上笔者只截取了部分代码,剩下部分都差不多,都是解析元数据进行赋值操作。
接下来就是重头戏refresh();
方法,这个方法是spring ioc 中最重要的方法。笔者将在下文中开始着重进行解析。