目前咱们剖析的代码曾经到了容器解决相干的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 公布!