08--SpringBoot启动容器创建与配置
上文分析了SpringBoot打印banner和如何自定义打印banner,接下来分析SpringBoot的ApplicationContext容器创建和初步配置,继续run方法
//创建应用上下文对象
context = createApplicationContext();
//获取异常报告对象
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
//准备上下文环境
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
1.创建ApplicationContext
protected ConfigurableApplicationContext createApplicationContext() {
// 如果当前的applicationContextClass为null,
// 则判断已经推断出的webApplicationType并创建不同的ApplicationContext容器
// 因为我们当前使用的是非web环境,所以会实例化AnnotationConfigApplicationContext
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
switch (this.webApplicationType) {
case SERVLET:
contextClass = Class.forName(DEFAULT_WEB_CONTEXT_CLASS);
break;
case REACTIVE:
contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
break;
default:
contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
}
} catch (ClassNotFoundException ex) {
throw new IllegalStateException("Unable create a default ApplicationContext, " + "please specify an ApplicationContextClass", ex);
}
}
//org.springframework.context.annotation.AnnotationConfigApplicationContext
return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}
// 接下来看看switch里的三个常量值是什么
// 默认web环境
public static final String DEFAULT_WEB_CONTEXT_CLASS = "org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext";
// 默认响应式web环境
public static final String DEFAULT_REACTIVE_WEB_CONTEXT_CLASS = "org.springframeworkboot.web.reactive.context.AnnotationConfigReactiveWebServerApplicationContext";
// 默认环境
public static final String DEFAULT_CONTEXT_CLASS = "org.springframework.context.annotation.AnnotationConfigApplicationContext";
我们当前使用的是非web环境,所以会实例化AnnotationConfigApplicationContext
AnnotationConfigApplicationContext
容器的定义是什么呢?
独立应用程序上下文,接受带注释的类作为输入,特别是带注释的类@Configuration,也支持@Componet,以及JSR-303等注解,实现基于Java的配置类加载Spring的应用上下文,查看类结构

这里会涉及到一部分Spring的知识,我们这里简单分析一下容器创建的过程,以及其中一些比较核心的组件,等该系列写完后,会开一个讲解Spring的专题!
打开AnnotationConfigApplicationContext的父类GenericApplicationContext,我们可以看到
private final DefaultListableBeanFactory beanFactory;
DefaultListableBeanFactory是整个Spring加载Bean最核心的组件,类结构如下

分析一下其中比较核心的组件
-
AliasRegistry接口,定义对Alias别名的增删改查
-
SimpleAliasRegistry类,实现了AliasRegistry接口,通过
private final Map<String, String> aliasMap = new ConcurrentHashMap<>(16);
aliasMap对别名实现存储 -
BeanFactory接口,用于访问Spring bean容器的根接口.其主要实现类有ListableBeanFactory和ConfigurableBeanFactory
-
DefaultSingletonBeanRegistry类,共享bean实例的通用注册表,实现 SingletonBeanRegistry。允许通过bean名称注册应该为注册表的所有调用者共享的单例实例。还支持DisposableBean在注册表关闭时销毁实例的注册 (可能与注册的单例相对应,也可能不相对应)。可以注册bean之间的依赖关系以强制执行适当的关闭顺序。该类主要用作BeanFactory实现的基类 ,分解单例bean实例的公共管理。请注意,ConfigurableBeanFactory 界面扩展了SingletonBeanRegistry界面。
请注意,此类假设既不是一个bean定义的概念,也不是bean实例具体的创建过程,而相比之下, AbstractBeanFactory以及DefaultListableBeanFactory (这从它继承)。或者也可以用作委托的嵌套助手。