目前咱们剖析的代码曾经到了容器解决相干的SpringBoot原理,代码如下:
public ConfigurableApplicationContext run(String... args) {
//DONE 扩大点 SpringApplicationRunListeners listeners.starting();
//DONE 配置文件的解决和形象封装 ConfigurableEnvironment
//容器相干解决
//1)外围就是创立了Context和BeanFactory对象,外部初始化了Reader和Scanner,加载了一些外部Bean
context = createApplicationContext();
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[] {ConfigurableApplicationContext.class }, context);
//2) 给容器Context、BeanFactory设置了一堆属性和组件,执行了initialize/listener的扩大点
//比拟重要属性有:singletonObjects 、beanDefinitionMap 、beanFactoryPostProcessors、applicationListeners
prepareContext(context, environment, listeners, applicationArguments,printedBanner);
//3) TODO 容器要害的扩大操作执行了,也是很多容器性能和第三方性能的扩大之处
refreshContext(context);
//其余逻辑
}
曾经剖析的阶段如下图:
prepareContext()筹备实现之后,接下来就是refreshContext()。容器要害的扩大操作执行了,也是很多容器性能和第三方性能的扩大之处,咱们来一起看下吧。
疾速摸一下refreshCotenxt的脉络
refreshCotenxt()办法最终调用了容器的refresh办法,咱们还是先来看下它的脉络,之后从两头抽丝剥茧的找到重点。
先来疾速的看下它的代码脉络:
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
整体由一个try-catch形成,外部有很多个办法组成,看上去让人找不到重点所在,感觉每个办法都挺重要的。
我第一次看的时候,每个办法,都离开从脉络到细节,剖析。
最初抓大放小,其实refresh在下面最重要的三个办法是:
invokeBeanFactoryPostProcessors 执行了容器扩大点,主动拆卸配置、其余技术的常扩大处
onRefresh 内嵌的web容器启动,默认是tomcat
finishBeanFactoryInitialization bean的实例化
那么,本着抓大放小的思维,其余的办法不是很重要,这个确认过程就不带大家一一去开展看每个办法了。
当然除了外围给大家剖析下面这三个办法,其余的会顺带提到下,让大家理解下就行。
明天咱们就来先refresh的看看第一个外围办法做了什么。
invokeBeanFactoryPostProcessors执行容器扩大点之前的次要操作
refresh()执行到invokeBeanFactoryPostProcessors是十分重要的逻辑,后面的办法大体能够概括如下图所示:
整个过程中,不是很重要,用浅蓝色标注的内容:
波及设置了一些无关紧要的值,startupDate、setSerializationId、BeanExpressionResolver等等
也设波及了根本对象汇合的初始化earlyApplicationEvents、earlyApplicationListeners
也标注了几个容器注入对象须要特地思考和疏忽的接口等
setignoreDependencyInterface 设置疏忽的接口,不会注册成bean
registerResolvableDependency 指明Spring外部一些接口 默认会注入的容器对象
绝对重要一点的点是,图中用绿色标注了下:
次要还补充了一些Spring本人的对Bean的扩大点BeanPostProcessor,Spring默认的BeanPostProcessor,补充一些BeanDefinition、registerSingleton补充一些外部的对象到汇合。
术语遍及BeanPostProcessor是什么?
之前BeanFactoryPostProcessor是对容器的扩大,次要有一个办法,能够给容器设置属性,补充一些单例对象,补充一些BeanDefinition。
那BeanPostProcessor是对bean的扩大,有before和after两类办法,对Bean如何做扩大,在bean的创立前后,给bean补充一些属性等。
invokeBeanFactoryPostProcessors之前的逻辑,咱们疾速过一下就好,当中并没有特地重要的逻辑,次要是Spring对外部的解决,给容器补充了一堆属性。
invokeBeanFactoryPostProcessors的外围脉络
大体理解了invokeBeanFactoryPostProcessors之前的次要操作后,接下来咱们外围首先来先看看这个办法的脉络,看看它次要做了写什么的?
protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
// Detect a LoadTimeWeaver and prepare for weaving, if found in the meantime
// (e.g. through an @Bean method registered by ConfigurationClassPostProcessor)
if (beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
}
乍一看,这个办法如同挺简略的, 只有2段逻辑,你很容易抓到重点
invokeBeanFactoryPostProcessors执行扩大点,这个应该是外围触发容器的扩大点中央。
依据条件,补充一个Bean的扩大操作,BeanPostProcessor,这个显著不是啥重点逻辑,之前做过很多相似的操作了。
如下图所示:
那你深刻到PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors这个办法是,你会发现如下一大坨的代码:
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
// Invoke BeanDefinitionRegistryPostProcessors first, if any.
Set<String> processedBeans = new HashSet<>();
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
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.
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
}
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
else {
// Invoke factory processors registered with the context instance.
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.
List<BeanFactoryPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<String> orderedPostProcessorNames = new ArrayList<>();
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (processedBeans.contains(ppName)) {
// skip - already processed in first phase above
}
else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class));
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
// First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory);
// Next, invoke the BeanFactoryPostProcessors that implement Ordered.
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.
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();
}
这个办法,初看上去的是有一点简单,然而没关系,你能够先摸清一下它的脉络:
1)首先次要有一个if-else组成
2)之后是间断的3个for循环
如下图:
好了,这就是这个办法的外围脉络了,接下来咱们别离来弄清楚,if-else逻辑在做什么,之后的3个for循环在做什么,这个办法根本就晓得在做什么了。
让咱们来看下第一个if-else在做什么呢?
if-esle外围脉络逻辑
第一个if-esle外围逻辑次要是判断了容器是否实现了BeanDefinitionRegistry这个接口,从而决定如何执行BeanFactoryPostProcessor的扩大操作。
BeanDefinitionRegistry这个接口,之前咱们遍及过,封装了对BeanDefinition常见操作的接口,容器默认实现了这个接口,所以个别它也代表了容器,能够通过实现的办法,保护容器内List<BeanDefinition>。
代码如下:
public static void invokeBeanFactoryPostProcessors(
ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) {
if (beanFactory instanceof BeanDefinitionRegistry) {
}else {
// Invoke factory processors registered with the context instance.
invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory);
}
}
容器默认是实现了BeanDefinitionRegistry接口,失常会执行if逻辑。因为if逻辑绝对简单,咱们先来看下,else逻辑在做什么,再去了解if逻辑。
else逻辑
else逻辑比较简单次要就是触发了入参中的beanFactoryPostProcessors的扩大办法postProcessBeanFactory(),代码如下:
private static void invokeBeanFactoryPostProcessors(
Collection<? extends BeanFactoryPostProcessor> postProcessors, ConfigurableListableBeanFactory beanFactory) {
for (BeanFactoryPostProcessor postProcessor : postProcessors) {
postProcessor.postProcessBeanFactory(beanFactory);
}
}
疑难:入参中这些外部的BeanFactoryPostProcessor这个是哪里来的?
是通过从容器中的一个属性 List<BeanFactoryPostProcessor> beanFactoryPostProcessors。
这个属性时之前通过listener等扩大点减少进来的一些Spring外部的BeanFactoryPostProcessor。次要有如下三个:
beanFactoryPostProcessors = {ArrayList@2882} size = 3
0 = {SharedMetadataReaderFactoryContextInitializer
$CachingMetadataReaderFactoryPostProcessor@2887}
1 = {ConfigurationWarningsApplicationContextInitializer
$ConfigurationWarningsPostProcessor@2888}
2 = {ConfigFileApplicationListener
$PropertySourceOrderingPostProcessor@2889}
咱们这里把它们称之为inernalBeanFactoryPostProcessors
如下图:
那最终else逻辑其实次要就是触发了这些外部BeanFactoryPostProcessor的postProcessBeanFactory()扩大办法而已。整体如下图所示:
至于这些扩大操作具体做了什么,咱们稍后在剖析,先整体摸清楚办法脉络在来看细节。
if逻辑
理解了else 的逻辑之后,咱们再看下if次要做了什么。因为if-else逻辑,其实默认是不会执行的else的,优先执行的必定是if。
这里要先遍及一些概念,才能够更好的了解if的代码逻辑。
术语遍及BeanDefinitionRegistryPostProcessor是什么?
BeanDefinitionRegistryPostProcessor
也是扩大点,继承自BeanFactoryPostProcessor,对BeanFactoryPostProcessor减少了一个扩大办法而已。
整体设计如下图所示:
BeanFactoryPostProcessor能够有两个扩大操作
也就是说,原来的BeanFactoryPostProcessor的扩大办法,从一个减少到了两个,一个是postProcessBeanFactory(),另一个事postProcessBeanDefinitionRegistry()。
另外一个要强调的其实是BeanFactoryPostProcessor起源有两个
1)容器中,当时通过扩大点退出的BeanFactoryPostProcessor
2)BeanDefinition中的,定义的然而没有实例化的BeanFactoryPostProcessor
如下图:
BeanFactoryPostProcessor能够有两个扩大操作、BeanFactoryPostProcessor起源有两个
这2点很要害,带着这个常识,咱们再看if逻辑,就会很容易。
if逻辑次要代码如下:
if (beanFactory instanceof BeanDefinitionRegistry) {
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory;
List<BeanFactoryPostProcessor> regularPostProcessors = new ArrayList<>();
List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) {
if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) {
BeanDefinitionRegistryPostProcessor registryProcessor =
(BeanDefinitionRegistryPostProcessor) postProcessor;
registryProcessor.postProcessBeanDefinitionRegistry(registry);
registryProcessors.add(registryProcessor);
}
else {
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.
List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
String[] postProcessorNames =
beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// Next, invoke the BeanDefinitionRegistryPostProcessors that implement Ordered.
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
boolean reiterate = true;
while (reiterate) {
reiterate = false;
postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
for (String ppName : postProcessorNames) {
if (!processedBeans.contains(ppName)) {
currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
processedBeans.add(ppName);
reiterate = true;
}
}
sortPostProcessors(currentRegistryProcessors, beanFactory);
registryProcessors.addAll(currentRegistryProcessors);
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
currentRegistryProcessors.clear();
}
// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);
}
这个if逻辑的代码脉络,次要的逻辑是有3个for+1while逻辑,其实能够依照扩大操作1和扩大操作2的执行划分开。
让咱们别离看下。
执行扩大办法1:postProcessBeanDefinitionRegistry()
执行扩大办法1时,首先就须要别离从两个起源开始执行,而且执行的是实现了BeanDefinitionRegistryPostProcessor的BeanFactoryPostProcessor。
次要逻辑能够概括如下图:
用文字解释下上图的话,就是:
1)容器中,之前减少的外部相干的BeanFactoryPostProcessor有没有实现这个BeanDefinitionRegistryPostProcessor接口减少了扩大办法postProcessBeanDefinitionRegistry()的?如果有,对应的所有BeanFactoryPostProcessor,通过for循环执行这个办法。并且记录这些执行的BeanFactoryPostProcessor和未执行的BeanFactoryPostProcessor。
2)容器中,之前减少的外部相干的BeanDefinition中,有没有定义为BeanFactoryPostProcessor的,如果有,依照实现了PrioriyOrder接口、Order接口、无Order接口的别离执行扩大办法postProcessBeanDefinitionRegistry(),应用了2for循环+一个while循环执行,执行实现记录这些BeanFactoryPostProcessor。
执行扩大办法2:postProcessBeanFactory()
之前执行扩大办法1的时候记录的所有BeanFactoryPostProcessor,包含扩大点之前增加的,BeanDefinition定义的。
咱们能够通过记录的这些BeanFactoryPostProcessor ,来在执行执行扩大办法2—postProcessBeanFactory()。
如下图所示:
整个if-else的逻辑的脉络,咱们就摸清楚了,至于这些扩大操作具体做了什么,咱们稍后在剖析,还是先整体摸清楚办法脉络在来看细节。
3个For循环的外围脉络逻辑
invokeBeanFactoryPostProcessors的外围脉络中,除了一个if-else逻辑,接下来的就是间断的3次for循环执行。
分为次要排序、排序、无程序要求的BeanFactoryPostProcessor三类,次要执行扩大点BeanFactoryPostProcessor的postProcessBeanFactory办法。
这个逻辑听下来,其实和之前if-else中的逻辑是很像的。只不过之前执行的是BeanDefinitionRegistryPostProcessor。
而且此时的BeanFactoryPostProcessor都来自与BeanDefinition中的。
你可能说,之前曾经执行过了BeanDefinition中的BeanFactoryPostProcessor了,怎么还有?
之前执行的是Spring外部定义好的一些BeanFactoryPostProcessor,在执行了if-else逻辑后,其实扫描进去了ClassPath下更多第三方和其余的BeanFactoryPostProcessor
这些新扫描进去BeanFactoryPostProcessor,参考之前BeanDefinitionRegistryPostProcessor的执行形式,执行了如下的扩大操作:
3个for的逻辑的脉络,其实并不简单,至于这些扩大操作具体做了什么,既然咱们摸清楚了整个办法invokeBeanFactoryPostProcessors的脉络了,咱们下一节马上就来剖析。
小结
最初,简略小结下,invokeBeanFactoryPostProcessors次要做的就是执行BeanDefinitionRegistryPostProcessor、BeanFactoryPostProcessor的2个扩大办法。这些BeanFactoryPostProcessors可能是外部Spring实现增加好的,也可能是来自ClassPath扫描进去的BeanFactoryPostProcessors。
这些扩大点具体执行了写什么,有哪些重点操作呢?咱们下一节一起来认真看看细节。咱们下节再见!
本文由博客一文多发平台 OpenWrite 公布!
发表回复