Spring的启动流程探索
run方法
我们都知道springboot工程是通过run方法启动的,如图:
Banner printedBanner = this.printBanner(environment);
就是我们熟悉的springboot工程启动的时候在控制台打印的log,我们也可以通过配置改变log的打印。
一,context = this.createApplicationContext()
我们先介绍
context = this.createApplicationContext();
方法,这个方法顾名思义是创建应用上下文的,应用上下文我们都知道是用来扫描Bean的,并且种类很多。那我们spring使用了应用上下文那些去获取Bean吗,打断点进入这个方法
可以看到在这里
new AnnotatedBeanDefinitionReader(this);
new了一个用于读取带有注解的Bean对应的BeanDefinition,还new了一个new ClassPathBeanDefinitionScanner(this);
用于从路径读取Bean的BeanDefinition。
在new AnnotatedBeanDefinitionReader
的时候会去调用它的构造方法,在它的构造方法里面会去将它的AnnotatedBeanDefinitionReader
的BeanDefinition加入到DefaultListableBeanFactory
这个类里面的beanDefinitionNames
和beanDefinitionMap
,这两个就是后面创建Bean必须的东西,所有Bean的注册底层都是使用的BeanDefinition。如图:
添加到
DefaultListableBeanFactory
这个类的beanDefinitionNames
和beanDefinitionMap
。
总的来说具体来说,createApplicationContext()
方法会根据指定的配置文件(通常是XML文件)或Java配置类来创建和初始化ApplicationContext。配置文件中包含了应用程序中各种bean的定义和配置信息,Spring会根据这些信息创建出对应的bean实例,并将它们注入到相应的对象中,从而完成整个应用程序的初始化。
二,this.prepareContext()
1
context.setEnvironment(environment);
这一步不用多说,就是将环境变量set到context中,设置上下文的环境。
2this.postProcessApplicationContext(context);
这步操作主要是对ApplicationContext
进行后置处理。那么做了哪些后置处理呢?我们点进去看下:
主要做了3部分:1.设置ApplicationContext的beanNameGenerator。2.设置ApplicationContext的ResourceLoader和ClassLoader。3.设置ApplicationContext类型转换service
3this.applyInitializers(context);
这个方法就是获取之前获取到的所有initializer类型的类,并进行初始化。
4listeners.contextPrepared(context);
这个方法是通知监听器 context 准备完成;
5if (this.logStartupInfo) { this.logStartupInfo(context.getParent() == null);
this.logStartupProfileInfo(context); }这个代码就是打印日志,这里不做过多描述。
6ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
这个方法就是获取DefaultListableBeanFactory的实例。
7beanFactory.registerSingleton(“springApplicationArguments”, applicationArguments);
这步操作是注册了一个单例,单例名为“springApplicationArguments”,值为applicationArguments。
8if (printedBanner != null) {beanFactory.registerSingleton("springBootBanner", printedBanner);}
这步是判断printedBanner是否为空,如果不为空,就注册一个名为springBootBanner,值为printedBanner的单例
9if (beanFactory instanceof DefaultListableBeanFactory) {((DefaultListableBeanFactory)beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);}
这个方法主要是配置bean如果重名,是否允许后一个bean覆盖前一个bean,默认是false,此时如果有同名的bean,注册到容器中,那么就会报异常。
10Set<Object> sources = this.getAllSources();
获取sources列表,这里可以获取到启动类的class
11
this.load(context, sources.toArray(new Object[0]));
这个方法就是加载启动类,将启动类注入到容器里面。
可以看到
beanDefinitionNames
和beanDefinitionMap
里面已经有6个了。都是主配置类。
12
listeners.contextLoaded(context);
这个方法我们点进去看下:
这里就是将在
SpringApplciation
的Initialize()
方法中注册的listener
中属于ApplicationContextAware
类型的bean都执行方法setApplicationContext
,同时将这些Listener都加入到ApplicationContext
中,并发布事件ApplicationPreparedEvent
三,this.refreshContext(context)
这个就是刷新容器的方法
1.
this.prepareRefresh()
,进入这个方法。
this.startupDate = System.currentTimeMillis();
设置容器启动的时间
this.closed.set(false);
容器的关闭标志位
this.active.set(true);
将容器状态设置为有效,
this.initPropertySources();
留给子类覆盖,初始化属性资源
this.getEnvironment().validateRequiredProperties();
创建并获取环境对象,验证需要的属性文件是否都已经放入环境中。
最后去判断刷新前的应用程序监听器集合是否为空,如果为空,则将监听器添加到集合中。
三,ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory()
这个用于获取设置容器序列化id和BeanFactory
1.
this.refreshBeanFactory();
,点进去看
首先使用了
CAS
去判断容器是否已经启动,没有启动就给beanFactory
设置一个序列化id。
设置的序列化id就是你的服务名称。
2.this.getBeanFactory();
,点进去看,调用了getBeanFactory
方法获取了beanFactory,而beanFactory是在这个通用上下文构造方法里面就创建了的DefaultListableBeanFactory
。
四,this.prepareBeanFactory(beanFactory)
点进去看
这个方法就是给工厂设置必须的工具,比如el表达式解析器,资源解析器,后置处理器等。
五,this.postProcessBeanFactory(beanFactory)
这个是留给子类的模板方法,允许子类对工厂执行一些处理,给Bean设置属性,单例Bean修改为多例,或者移除BeanDefinition从而避免某个Bean在spring容器中的创建。例如:
又或者用它的子类接口
BeanDefinitionRegistryPostProcessor
,如图
最后别忘记把这两个配置类注入到容器当中
六,this.invokeBeanFactoryPostProcessors(beanFactory)
这个就是去调用Bean工厂主处理器,
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
// 将已经执行过的BeanFactoryPostProcessor存储在processedBeans,防止重复执行
Set<String> processedBeans = new HashSet<>();
// 此处条件成立,BeanFactory类型为DefaultListableBeanFactory,而DefaultListableBeanFactory实现了BeanDefinitionRegistry接口
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
// 用来存放BeanFactoryPostProcessor对象
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
// 用来存放BeanDefinitionRegistryPostProcessor对象
// 方便统一执行实现了BeanDefinitionRegistryPostProcessor接口父类的方法
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
// 处理外部定义的BeanFactoryPostProcessor,将BeanDefinitionRegistryPostProcessor与BeanFactoryPostProcessor区分开
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
// 如果为BeanDefinitionRegistryPostProcessor类型
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
// 强转成BeanDefinitionRegistryPostProcessor
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
// 如果是BeanDefinitionRegistryPostProcessor类型,直接执行postProcessBeanDefinitionRegistry方法
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
// 如果不是BeanDefinitionRegistryPostProcessor类型
// 则将外部集合中的BeanFactoryPostProcessor存放到regularPostProcessors用于后续一起执行
regularPostProcessors.add(postProcessor);
}
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
// Separate between BeanDefinitionRegistryPostProcessors that implement
// PriorityOrdered, Ordered, and the rest.
// 此处的currentRegistryProcessors存放当前需要执行的BeanDefinitionRegistryPostProcessor
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
// TODO 首先,调用实现 PriorityOrdered 的 BeanDefinitionRegistryPostProcessor。
// 获取所有实现了BeanDefinitionRegistryPostProcessor接口的类名
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
// 判断当前类是否实现了PriorityOrdered接口
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
// 将BeanDefinitionRegistryPostProcessor存入currentRegistryProcessors
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
// 提前存放到processedBeans,避免重复执行,但是此处还未执行
processedBeans.add(ppName);
}
}
// 对currentRegistryProcessors接口中的BeanDefinitionRegistryPostProcessor进行排序,方便后续执行
sortPostProcessors(currentRegistryProcessors, beanFactory);
// 添加到registryProcessors集合,用于后续执行父接口的postProcessBeanFactory方法
registryProcessors.addAll(currentRegistryProcessors);
// 遍历集合,执行BeanDefinitionRegistryPostProcessor.postProcessBeanDefinitionRegistry()方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
// 执行完毕后,将currentRegistryProcessors清空
currentRegistryProcessors.clear();
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
// TODO 接下来,调用实现 Ordered 的 BeanDefinitionRegistryPostProcessors。
// 这里为什么要再次获取BeanDefinitionRegistryPostProcessor
// 是因为有可能在上面方法执行过程中添加了BeanDefinitionRegistryPostProcessor,所以这里再次获取
// 而下面处理BeanFactoryPostProcessor的时候又不需要重复获取了是为什么呢?
// 因为添加BeanFactoryPostProcessor与BeanDefinitionRegistryPostProcessor只能在BeanDefinitionRegistryPostProcessor
// 中添加,在BeanFactoryPostProcessor是无法添加的,具体看方法参数就懂了
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
// 判断当前bean没有被执行过,并且实现了Ordered接口
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
// getBean() 如果BeanFactory中没有该Bean则会去创建该Bean
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
// 以下操作和上面是一样的,排序-->添加到registryProcessors-->执行-->清空currentRegistryProcessors
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
// TODO 最后处理没有实现Ordered与PriorityOrdered接口的BeanDefinitionRegistryPostProcessor
boolean reiterate = true;
while (reiterate) {
reiterate = false;
// 再次获取BeanDefinitionRegistryPostProcessor
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
// 将本次要执行的BeanDefinitionRegistryPostProcessor存放到currentRegistryProcessors
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
// 提前存放到processedBeans,避免重复执行
processedBeans.add(ppName);
reiterate = true;
}
}
// 此处的排序已经没有意义了
sortPostProcessors(currentRegistryProcessors, beanFactory);
// 将本次执行的BeanDefinitionRegistryPostProcessor添加到registryProcessors
registryProcessors.addAll(currentRegistryProcessors);
// 执行
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
// 清空
currentRegistryProcessors.clear();
}
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
// TODO 现在,调用到目前为止处理的所有处理器的 postProcessBeanFactory 回调。
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
// Invoke factory processors registered with the context instance.
// BeanFactory如果不归属于BeanDefinitionRegistry类型,则直接执行beanFactoryPostProcessor
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the bean factory post-processors apply to them!
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
// Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
// Ordered, and the rest.
// 用于存放实现了priorityOrdered接口的BeanFactoryPostProcessor
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
// 用于存放实现了ordered接口的BeanFactoryPostProcessor名称
List<String> orderedPostProcessorNames = new ArrayList<>();
// 用于存放无排序的BeanFactoryPostProcessor名称
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
// 如果已经执行过了,则不做处理
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
// 如果实现了PriorityOrdered
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
// 如果实现了Ordered
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
// 无排序
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
// TODO 首先,调用实现 PriorityOrdered 的 BeanFactoryPostProcessor。
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
// TODO 接下来,调用实现 Ordered 的 BeanFactoryPostProcessors。
List<BeanFactoryPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
for (String postProcessorName : orderedPostProcessorNames) {
orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
sortPostProcessors(orderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);
// Finally, invoke all other BeanFactoryPostProcessors.
// TODO 最后,调用所有其他 BeanFactoryPostProcessor。
List<BeanFactoryPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
for (String postProcessorName : nonOrderedPostProcessorNames) {
nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class));
}
invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);
// Clear cached merged bean definitions since the post-processors might have
// modified the original metadata, e.g. replacing placeholders in values...
// 清空缓存
beanFactory.clearMetadataCache();
}
总的来说回去执行实现了BeanFactoryPostProcessor
接口的类重写的方法,直接说最重要的一个子类-ConfigurationClassPostProcessor
来看看详解:
public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
List<BeanDefinitionHolder> configCandidates = new ArrayList<BeanDefinitionHolder>();
//获取所有BeanDefinition的名称
String[] candidateNames = registry.getBeanDefinitionNames();
for (String beanName : candidateNames) {
BeanDefinition beanDef = registry.getBeanDefinition(beanName);
//如果BeanDefinition 中的configurationClass 属性为full 或者lite ,则意味着已经处理过了,直接跳过
if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) ||
ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) {
if (logger.isDebugEnabled()) {
logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
}
}
//如果符合配置类候选条件(@Configuration修饰),加入configCandidates集合,后面根据优先级实例化配置bean
else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
}
}
//如果没有配置类(@Configuration)则返回,这里找到了一个启动类,所以不用返回。
if (configCandidates.isEmpty()) {
return;
}
// 根据定义的Order排序
Collections.sort(configCandidates, new Comparator<BeanDefinitionHolder>() {
@Override
public int compare(BeanDefinitionHolder bd1, BeanDefinitionHolder bd2) {
int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0;
}
});
//如果BeanFactory中没设置componentScanBeanNameGenerator,则使用该componentScanBeanNameGenerator
SingletonBeanRegistry sbr = null;
if (registry instanceof SingletonBeanRegistry) {
sbr = (SingletonBeanRegistry) registry;
if (!this.localBeanNameGeneratorSet && sbr.containsSingleton(CONFIGURATION_BEAN_NAME_GENERATOR)) {
BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
this.componentScanBeanNameGenerator = generator;
this.importBeanNameGenerator = generator;
}
}
// 实例化ConfigurationClassParser 为了解析每个@ configuration类
ConfigurationClassParser parser = new ConfigurationClassParser(
this.metadataReaderFactory, this.problemReporter, this.environment,
this.resourceLoader, this.componentScanBeanNameGenerator, registry);
Set<BeanDefinitionHolder> candidates = new LinkedHashSet<BeanDefinitionHolder>(configCandidates);
Set<ConfigurationClass> alreadyParsed = new HashSet<ConfigurationClass>(configCandidates.size());
do {
//借助ConfigurationClassParser完成配置类解析,加载所有的配置类(@Configuration)到资源(Resource)中
parser.parse(candidates);
//配置类不能用final,因为要用cglib生成代理对象
parser.validate();
Set<ConfigurationClass> configClasses = new LinkedHashSet<ConfigurationClass>(parser.getConfigurationClasses());
configClasses.removeAll(alreadyParsed);
// 如果reader为null,则实例化ConfigurationClassBeanDefinitionReader
if (this.reader == null) {
this.reader = new ConfigurationClassBeanDefinitionReader(
registry, this.sourceExtractor, this.resourceLoader, this.environment,
this.importBeanNameGenerator, parser.getImportRegistry());
}
//用ConfigurationClassBeanDefinitionReader解析资源Resource得到BeanDefiniton,然后注册到IOC容器中
this.reader.loadBeanDefinitions(configClasses);
//加入到alreadyParsed中,用于去重
alreadyParsed.addAll(configClasses);
//将candidates进行清空
candidates.clear();
//如果registry中注册的bean的数量 大于 之前获得的数量,则意味着在解析过程中又新加入了很多,那么就需要对其进行解析
if (registry.getBeanDefinitionCount() > candidateNames.length) {
String[] newCandidateNames = registry.getBeanDefinitionNames();
Set<String> oldCandidateNames = new HashSet<String>(Arrays.asList(candidateNames));
Set<String> alreadyParsedClasses = new HashSet<String>();
for (ConfigurationClass configurationClass : alreadyParsed) {
alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
}
for (String candidateName : newCandidateNames) {
if (!oldCandidateNames.contains(candidateName)) {
BeanDefinition bd = registry.getBeanDefinition(candidateName);
if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
!alreadyParsedClasses.contains(bd.getBeanClassName())) {
candidates.add(new BeanDefinitionHolder(bd, candidateName));
}
}
}
candidateNames = newCandidateNames;
}
}
while (!candidates.isEmpty());
// Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
if (sbr != null) {
if (!sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
// 如果SingletonBeanRegistry 不包含org.springframework.context.annotation.ConfigurationClassPostProcessor.importRegistry
// 则注册一个,bean 为 ImportRegistry. 一般都会进行注册的
sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
}
}
//清除缓存
if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) {
((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
}
}
点进去看一下。
再点进去。
在这里会拿到主启动类,然后再去扫描主启动类下面的Bean。
从这里进去。
这就很清晰了,去获取项目中所有使用了@Component
注解Bean。
当然,这个类
ConfigurationClassParser
里面不止扫描使用了@Component
注解的Bean。还有@Bean
注解等等,如图
光是知道在哪里把使用了这些注解的Bean解析出来还不够,需要知道怎么解析出来的,就像我们学习Spring的时候那样,是通过应用上下文扫描出来的,如图
点进
this.componentScanParser.parse
这个方法
可以看到
new ClassPathBeanDefinitionScanner
,在这里new了一个应用上下文扫描,这就是原理。
而且和我们介绍context = this.createApplicationContext()
方法,里面构造函数创建的两个应用上下文中的一个是一样的。
至此项目中所有的Bean都被invokeBeanFactoryPostProcessors
这个方法(ConfigurationClassPostProcessor
最关键)解析出来。
并且通过
this.reader.loadBeanDefinitions(configClasses);
这个方法放到DefaultListableBeanFactory
这个类里面的beanDefinitionNames
和beanDefinitionMap
,如图
点进去,再点进这个方法,
再点进这个方法,可以看到现在将我
beanName
为getgiao
的Bean注册到DefaultListableBeanFactory
这个类里面的beanDefinitionNames
和beanDefinitionMap
里面。
如图:
七,this.finishBeanFactoryInitialization(beanFactory)
这个方法是将DefaultListableBeanFactory
这个类里面的beanDefinitionNames
和beanDefinitionMap
初始化的,包括Spring三级缓存啊,这个下次再讲了。
转载自:https://juejin.cn/post/7267800436261748777