开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 2 天,点击查看活动详情
public ConfigurableApplicationContext run(String... args) {
//1 创建StopWatch对象
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
//2 设置Headless模式
configureHeadlessProperty();
//3 创建事件发布器
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
// 将main方法的args参数封装到一个对象中
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
//4 准备容器环境信息
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
configureIgnoreBeanInfo(environment);
//5.打印Banner
Banner printedBanner = printBanner(environment);
//6.创建IOC容器和Bean工厂
context = createApplicationContext();
//7.初始化异常报告器
exceptionReporters = getSpringFactoriesInstances(
SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
//8.初始化IOC容器
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
refreshContext(context);
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
listeners.started(context);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}
进入第八步,初始化IOC容器
八、初始化IOC容器
private void prepareContext(ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
//设置容器运行环境
context.setEnvironment(environment);
//8.1 后置处理器处理IOC容器
postProcessApplicationContext(context);
//8.2 初始化容器
applyInitializers(context);
//8.3 发布容器初始化事件
listeners.contextPrepared(context);
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
// Add boot specific singleton beans
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
if (beanFactory instanceof DefaultListableBeanFactory) {
((DefaultListableBeanFactory) beanFactory)
.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
//8.4注册主启动类
load(context, sources.toArray(new Object[0]));
//8.5发布容器准备就绪事件
listeners.contextLoaded(context);
}
8.1 后置处理器处理IOC容器
protected void postProcessApplicationContext(ConfigurableApplicationContext context) {
//8.1.1 如果BeanName生成器不为空则注册BeanName生成器
if (this.beanNameGenerator != null) {
context.getBeanFactory().registerSingleton(
AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR,
this.beanNameGenerator);
}
//8.1.2 如果资源加载器不为空则设置资源加载器和类加载器
if (this.resourceLoader != null) {
if (context instanceof GenericApplicationContext) {
((GenericApplicationContext) context)
.setResourceLoader(this.resourceLoader);
}
if (context instanceof DefaultResourceLoader) {
((DefaultResourceLoader) context)
.setClassLoader(this.resourceLoader.getClassLoader());
}
}
//8.1.3 如果类型转换器不为空则设置类型转换器
if (this.addConversionService) {
context.getBeanFactory().setConversionService(
ApplicationConversionService.getSharedInstance());
}
}
- BeanName生成器 生成Bean名称
- resourceLoader资源加载器 通过url加载各种资源(xml,text等)
- conversionService类型转换器 将配置转换成对应类型
这里只会向IOC容器中注入类型转换器(在第4步准备容器环境信息时创建的)
8.2 初始化容器
protected void applyInitializers(ConfigurableApplicationContext context) {
for (ApplicationContextInitializer initializer : getInitializers()) {
Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(
initializer.getClass(), ApplicationContextInitializer.class);
Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
initializer.initialize(context);
}
}
获取所有初始化器,执行初始化方法
protected void applyInitializers(ConfigurableApplicationContext context) {
for (ApplicationContextInitializer initializer : getInitializers()) {
Class<?> requiredType = GenericTypeResolver.resolveTypeArgument(
initializer.getClass(), ApplicationContextInitializer.class);
Assert.isInstanceOf(requiredType, context, "Unable to call initializer.");
initializer.initialize(context);
}
}
这里的初始化器是在SpringApplication构造器的第2步设置进来的,通过Sping的SPI机制创建了META-INF/spring.factories下所有的ApplicationContextInitializer实现类
8.3 发布容器初始化事件
发布容器初始化事件: ApplicationContextInitializedEvent
@Override
public void contextPrepared(ConfigurableApplicationContext context) {
this.initialMulticaster.multicastEvent(new ApplicationContextInitializedEvent(
this.application, this.args, context));
}
8.4 注册主启动类
protected void load(ApplicationContext context, Object[] sources) {
if (logger.isDebugEnabled()) {
logger.debug(
"Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
}
//8.4.1创建BeanDefinition解析器
BeanDefinitionLoader loader = createBeanDefinitionLoader(
getBeanDefinitionRegistry(context), sources);
//设置Bean命名器
if (this.beanNameGenerator != null) {
loader.setBeanNameGenerator(this.beanNameGenerator);
}
//设置资源加载器
if (this.resourceLoader != null) {
loader.setResourceLoader(this.resourceLoader);
}
//设置环境
if (this.environment != null) {
loader.setEnvironment(this.environment);
}
//8.4.2 加载源信息到注册器中
loader.load();
}
8.4.1 创建BeanDefinition解析器
这里首先会先获取注册器,因为SpringBoot创建的IOC容器本身就继承了注册器(BeanDefinitionRegistry)功能,所以会直接将创建的IOC容器返回
private BeanDefinitionRegistry getBeanDefinitionRegistry(ApplicationContext context) {
if (context instanceof BeanDefinitionRegistry) {
return (BeanDefinitionRegistry) context;
}
if (context instanceof AbstractApplicationContext) {
return (BeanDefinitionRegistry) ((AbstractApplicationContext) context).getBeanFactory();
}
throw new IllegalStateException("Could not locate BeanDefinitionRegistry");
}
sources就是构造器时通过栈获取到的启动类,然后直接创建了一个BeanDefinition加载器
protected BeanDefinitionLoader createBeanDefinitionLoader(BeanDefinitionRegistry registry, Object[] sources) {
return new BeanDefinitionLoader(registry, sources);
}
在构造器中创建了用于BeanDefinition解析的组件
BeanDefinitionLoader(BeanDefinitionRegistry registry, Object... sources) {
Assert.notNull(registry, "Registry must not be null");
Assert.notEmpty(sources, "Sources must not be empty");
this.sources = sources;
//注解读取器
this.annotatedReader = new AnnotatedBeanDefinitionReader(registry);
//xml读取器
this.xmlReader = new XmlBeanDefinitionReader(registry);
if (isGroovyPresent()) {
this.groovyReader = new GroovyBeanDefinitionReader(registry);
}
//类路径下的Bean定义扫描器
this.scanner = new ClassPathBeanDefinitionScanner(registry);
//类过滤器
this.scanner.addExcludeFilter(new ClassExcludeFilter(sources));
}
8.4.2 加载源信息到注册器
将数据源(启动类)解析并加载到注册器中(SpringBoot的IOC容器)
public int load() {
int count = 0;
//sources为启动类
for (Object source : this.sources) {
count += load(source);
}
return count;
}
source为启动类,所以是Class类型
private int load(Object source) {
Assert.notNull(source, "Source must not be null");
//如果class类
if (source instanceof Class<?>) {
return load((Class<?>) source);
}
//如果是资源类
if (source instanceof Resource) {
return load((Resource) source);
}
//如果是Package
if (source instanceof Package) {
return load((Package) source);
}
//如果是字符
if (source instanceof CharSequence) {
return load((CharSequence) source);
}
throw new IllegalArgumentException("Invalid source type " + source.getClass());
}
启动类被@SpringBootApplication标注
@SpringBootApplication继承了@SpringBootConfiguration,
@SpringBootConfiguration继承了@Configuration
@Configuration继承了@Component注解
所以启动类会被annotatedReader解析
private int load(Class<?> source) {
if (isGroovyPresent()
&& GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
// Any GroovyLoaders added in beans{} DSL can contribute beans here
GroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source,
GroovyBeanDefinitionSource.class);
load(loader);
}
//如果含有@Component注解
if (isComponent(source)) {
this.annotatedReader.register(source);
return 1;
}
return 0;
}
最后会被spring的注解解析将启动类解析成BeanDefinition到注册器中(SpringBoot的IOC容器继承了注册器)
<T> void doRegisterBean(Class<T> beanClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
// 包装为BeanDefinition
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
abd.setInstanceSupplier(instanceSupplier);
// 解析Scope信息,决定作用域
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
// 生成Bean的名称
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
// 解析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,将BeanDefinition注册到IOC容器中
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
8.5 发布容器准备就绪事件
将监听器添加容器中,发布容器准备就绪事件ApplicationPreparedEvent
public void contextLoaded(ConfigurableApplicationContext context) {
for (ApplicationListener<?> listener : this.application.getListeners()) {
if (listener instanceof ApplicationContextAware) {
((ApplicationContextAware) listener).setApplicationContext(context);
}
context.addApplicationListener(listener);
}
this.initialMulticaster.multicastEvent(new ApplicationPreparedEvent(this.application, this.args, context));
}
总结
- 发布容器初始化事件: ApplicationContextInitializedEvent
- 创建BeanDefinition解析器并且将启动类加载到注册器中
- 发布容器准备就绪事件ApplicationPreparedEvent