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()
1context.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
11this.load(context, sources.toArray(new Object[0]));
这个方法就是加载启动类,将启动类注入到容器里面。
可以看到beanDefinitionNames
和beanDefinitionMap
里面已经有6个了。都是主配置类。
12listeners.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工厂主处理器,
java复制代码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 来看看详解:
java复制代码public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) { List<BeanDefinitionHolder> configCandidates = new ArrayList<>(); //获取所有的BeanDefinitionName String[] candidateNames = registry.getBeanDefinitionNames(); for (String beanName : candidateNames) { BeanDefinition beanDef = registry.getBeanDefinition(beanName); // https://docs.spring.io/spring/docs/5.1.8.RELEASE/spring-framework-reference/core.html#beans-java-basic-concepts // Full @Configuration vs “lite” @Bean mode if (ConfigurationClassUtils.isFullConfigurationClass(beanDef) || ConfigurationClassUtils.isLiteConfigurationClass(beanDef)) { if (logger.isDebugEnabled()) { logger.debug("Bean definition has already been processed as a configuration class: " + beanDef); } } // 校验是否为配置类 // 配置类分为两种 Full @Configuration vs “lite” @Bean mode // 校验之后在 BeanDefinition 中添加标志属性 // 如果满足条件则加入到configCandidates else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) { // 如果是配置类,就放到 configCandidates 变量中 configCandidates.add(new BeanDefinitionHolder(beanDef, beanName)); } } // Return immediately if no @Configuration classes were found if (configCandidates.isEmpty()) { return; } // Sort by previously determined @Order value, if applicable configCandidates.sort((bd1, bd2) -> { int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition()); int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition()); return Integer.compare(i1, i2); }); // Detect any custom bean name generation strategy supplied through the enclosing application context SingletonBeanRegistry sbr = null; // 传入的 registry 是 DefaultListableBeanFactory if (registry instanceof SingletonBeanRegistry) { sbr = (SingletonBeanRegistry) registry; if (!this.localBeanNameGeneratorSet) { //获取自定义BeanNameGenerator,一般情况下为空 BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR); if (generator != null) { this.componentScanBeanNameGenerator = generator; this.importBeanNameGenerator = generator; } } } if (this.environment == null) { this.environment = new StandardEnvironment(); } // Parse each @Configuration class // new ConfigurationClassParser,用来解析 @Configuration 类 ConfigurationClassParser parser = new ConfigurationClassParser( this.metadataReaderFactory, this.problemReporter, this.environment, this.resourceLoader, this.componentScanBeanNameGenerator, registry); // 将 configCandidates 转成 set candidates , 去重 Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates); Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size()); do { // 解析配置类 parser.parse(candidates); parser.validate(); Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses()); configClasses.removeAll(alreadyParsed); // Read the model and create bean definitions based on its content if (this.reader == null) { this.reader = new ConfigurationClassBeanDefinitionReader( registry, this.sourceExtractor, this.resourceLoader, this.environment, this.importBeanNameGenerator, parser.getImportRegistry()); } // Import类,@Bean,@ImportResource 转化为 BeanDefinition this.reader.loadBeanDefinitions(configClasses); alreadyParsed.addAll(configClasses); candidates.clear(); // 再获取一下容器中BeanDefinition的数据,如果发现数量增加了,说明有新的BeanDefinition被注册了 if (registry.getBeanDefinitionCount() > candidateNames.length) { String[] newCandidateNames = registry.getBeanDefinitionNames(); Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames)); Set<String> alreadyParsedClasses = new HashSet<>(); 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 && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) { sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry()); } if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) { // Clear cache in externally provided MetadataReaderFactory; this is a no-op // for a shared cache since it'll be cleared by the ApplicationContext. ((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三级缓存啊,这个下次再讲了。