1.刷新应用上下文的准备
this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
1.上文初始化了context,这里说的准备工作就相当于给context里面的属性进行设置;
2.完成一些bean对象的创建;
我们自己写的核心启动类bean对象的创建也在prepareContext这个方法里完成。
1.1.设置应用上下的属性
1.1.1.设置environment
context.setEnvironment(environment);
设置容器环境
1.1.2.postProcessApplicationContext
postProcessApplicationContext(context);
执行容器后置处理
上一篇文章说到,在初始化应用上下文时调用BeanUtils.instantiateClass(contextClass),就已经创建了IOC容器对象;
context.getBeanFactory()就是获取容器对象,那么setConversionService就是给IOC容器设置转换服务(转换器);
转换器:比如我们在容器中可以把一些整数的字符串转换为整形。
1.1.3.applyInitializers
applyInitializers(context);
应用初始化器。
····getInitializers()获取到初始化器(执行run方法钱准备阶段,在SpringApplication的构造方法里,准备的初始化器),遍历启动执行(initializer.initialize(context))。
1.1.4.listeners.contextPrepared(context);
向各个监听器发送容器已经准备好的事件
····遍历监听器,将context发送给监听器。
完成了前三步,应用上下文的设置基本完成了,就发送给各个监听器。
这些监听器是SpringApplicationRunListeners类型的,根据之前的分析可以知道,
这个listeners只有一个值,就是EventPublishingRunListener(启动监听器)。
1.2.创建需要的bean对象
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
1.2.1.封装args
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
这个applicationArguments,就是我们传入的main方法的args(命令行参数)
····将main方法的args参数封装成单例bean,注册进IOC容器。
1.2.2.封装banner
如果printedBanner不为空,那么也会被封装成单例bean;
这里我没有设置banner.txt,所以为null。
1.2.3.设置允许bean的定义信息被覆盖
判断这个beanFactory是不是DefaultListableBeanFactory类型;
如果是,就设置允许bean的定义信息被覆盖;
显然,之前已经知道这个IOC(beanFactory)容器就是DefaultListableBeanFactory类型的。
1.2.4.判断当前是否是懒加载
如果是就设置LazyInitializationBeanFactoryPostProcessor
1.3.获取资源并加载启动类
1.3.1.获取source
Set<Object> sources = this.getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
····source是我们的启动类
1.3.2.将启动类注入容器
this.load(context, sources.toArray(new Object[0]));
sources是一个集合,取出我们的启动类。
load方法,通过核心启动类的字节码,生成实例对象,设置到IOC容器中。
- createBeanDefinitionLoader:方法两个参数;
- this.getBeanDefinitionRegistry(context);
- sources;
所以将context向上造型成BeanDefinitionRegistry;
Spring容器在启动的时候,会先将类解析成BeanDefinition对象
然后将BeanDefinition存到DefaultListableBeanFactory里面的一个map中
再看看这个BeanDefinitionLoader的构造方法
- annotatedReader:注解形式的Bean定义读取器(Component等)。
- xmlReader:xml配置形式的Bean定义读取器;
- scanner:类路径扫描Bean定义读取器;
- addExcludeFilter:扫描器添加排除过滤器。
经过前面步骤,loader(BeanDefinitionLoader)对象被创建出来了。
loader再调用load方法
又调用load方法再调用load方法
isComponent判断source启动类上面有没有Component注解;
很明显是有,那么就使用注解形式的bean定义读取器,将启动类的BeanDefinition注册进beanDefinitionMap。
这个componentClasses是传入的启动类resource。
在这个doRegisterBean方法里面,创建并设置AnnotatedGenericBeanDefinition的属性,当然是启动类相关的。
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name, @Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier, @Nullable BeanDefinitionCustomizer[] customizers) {
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
if (!this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
abd.setInstanceSupplier(supplier);
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
String beanName = name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry);
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
int var10;
int var11;
if (qualifiers != null) {
Class[] var9 = qualifiers;
var10 = qualifiers.length;
for(var11 = 0; var11 < var10; ++var11) {
Class<? extends Annotation> qualifier = var9[var11];
if (Primary.class == qualifier) {
abd.setPrimary(true);
} else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
} else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
if (customizers != null) {
BeanDefinitionCustomizer[] var13 = customizers;
var10 = customizers.length;
for(var11 = 0; var11 < var10; ++var11) {
BeanDefinitionCustomizer customizer = var13[var11];
customizer.customize(abd);
}
}
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
}
····设置这个beanDefinition的scop和beanName,然后通过AnnotatedGenericBeanDefinition
和beanName构建一个beandefinition的持有对象。
····registerBeanDefinition看下图:
····这里又调用registerBeanDefinition方法,这里调用的具体实现时DefaulListableBeanDefinition的实现,传递的参数时beanName和BeanDefinition
····在DefaultListableBeanFactory的registerBeanDefinition方法中,将beanName和beanDefinition分别作为key、value添加到beanDefinitionMap中。
核心启动类存入了beanDefinitionMap,并且在之前将这个beanDefinition设置成了singleton;
那么之后会从beanDefinitionMap中取出beanDefinition;
beanDefinition里面又存有启动类的Class字节码;
通过反射可以实例出对象,然后存到DefaultListableBeanFactory的单例池中;
单例池就是这个ConcurrentHashMap,这个singletonBeanNamesByType。
1.4.发布容器加载事件
启动类添加到了beanDefinitionMap;
那么刷新应用上下文的准备工作就只剩最后一步;
listeners.contextLoaded(context);
1.5.观察context
刷新应用上下文前的准备工作做完之后,我们看看context的属性值
····其实从这里也可以看出来,启动类只是添加到了beanDefinitionMap里面,还没有生成实例注入到单例池里面。