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