Spring【版本5.2.2】容器初始化过程(三)refresh(二)

接着上文,来说说try部分的功能,至于为什么这部分,放在try里面,而不包括前面三个,留个坑,后续研究。

4. postProcessBeanFactory

为容器的某些子类指定特殊的BeanPost事件处理器,空方法,可能会在web、tx等等其他模块用到

5. invokeBeanFactoryPostProcessors
/**
	 * Instantiate and invoke all registered BeanFactoryPostProcessor beans,
	 * respecting explicit order if given.
	 * <p>Must be called before singleton instantiation.
	 * 实例化并调用所有已注册的BeanFactoryPostProcessor bean,如果给定,则遵循显式顺序,必须在单例化之前调用。
	 */
	protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
		/*
		 * 这个地方需要注意getBeanFactoryPostProcessors()是获取手动给Spring的BeanFactoryPostProcessor
		 * 就是程序员自己写的,并且没有交给spring管理,就是没有加上@Component
		 * 比如org.springframework.demo.ioc.demo1.factory.MyBeanFactoryPostProcessor
		 * 为什么getBeanFactoryPostProcessors()得不到带有@Compnent的bd?
		 * getBeanFactoryPostProcessors() 这个方法直接过去一个list,这个list是在
		 * AnnotationConfigApplicationContext被定义,还没人给他赋值。
		 * 所谓的自定义的,就是手动调用
		 * AnnotationConfigApplicationContext.addBeanFactoryPostProcessor(在父类里面的方法)
		 * 见下面的详解
		 */
		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()));
		}
	}

在跟进最终的执行方法,这个例子里面的通过getBeanFactoryPostProcessors()传过来的值是空的list,里面没有值

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<>();

			// 自定义的beanFactoryPostProcessors,咱们现在的这个demo是空的,所以暂时过掉
			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.
			// [不要在这里初始化factoryBean:我们需要保留所有常规的bean未初始化,
			// 以便让bean工厂后置处理器应用于它们!
			// 将实现优先顺序的beanDefinitionRegistryPostprocessor与其它的分开。]
			// 这个currentRegistryProcessors放的是spring内部自己实现的BeanDefinitionRegistryPostProcessor
			// 跟上面的registryProcessors要区分
			List<BeanDefinitionRegistryPostProcessor> currentRegistryProcessors = new ArrayList<>();

			// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
			// 首先,调用实现PriorityOrdered的BeanDefinitionRegistryPostProcessors。
			// BeanDefinitionRegistryPostProcessor 等于 BeanFactoryPostProcessor
			// 就一个org.springframework.context.annotation.internalConfigurationAnnotationProcessor
			String[] postProcessorNames =
					beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);


			/* 这个地方,可以得到一个BeanFactoryPostProcessor,因为是Spring默认在最开始的时候自己注册的
			 * 威慑呢要在最开始注册这个呢?
			 * 因为spring的工厂需要解析去扫描等功能
			 * 而这些功能都是需要在spring工厂初始化完成之前执行
			 * 要么在工厂最开始的时候,要么在工厂初始化之中,反正不在之后
			 * 因为如果在之后,就没有意义了,因为那时候已经需要使用工厂了
			 * 所以这里spring 在一开始就注册了一个BeanFactoryPostProcessor,用来查收SpringFactory的实例化
			 * 在这个地方断点,可以知道这个类叫ConfigurationClassPostProcessor
			 * ConfigurationClassPostProcessor,这个类干嘛的呢,他能查收spring工厂的实例化
			 */
			for (String ppName : postProcessorNames) {
				if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
					currentRegistryProcessors.add(beanFactory.getBean(ppName, 
																BeanDefinitionRegistryPostProcessor.class));
					processedBeans.add(ppName);
				}
			}
			// 给currentRegistryProcessors排序
			sortPostProcessors(currentRegistryProcessors, beanFactory);
			// 合并到 List<BeanDefinitionRegistryPostProcessor> 中
			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);

			// 合并list
			registryProcessors.addAll(currentRegistryProcessors);
			// 调用三
			invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry);
			// 这个list是一个临时变量,所以需要删除
			currentRegistryProcessors.clear();

			// Finally, invoke all other BeanDefinitionRegistryPostProcessors until no further ones appear.
			// [最后,调用所有其他的BeanDefinitionRegistryPostProcessors,直到没有其他的出现。]
			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.
			//执行BeanFactoryPostProcessor的回调,前面不是吗?
			//前面执行的BeanFactoryPostProcessor的子类BeanDefinitionRegistryPostProcessor的回调
			//这是执行的是BeanFactoryPostProcessor    postProcessBeanFactory
			// 调用五
			invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
			// 调用六
			// 自定义BeanFactoryPostProcessor
			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!
	    // 找出所有实现BeanFactoryPostProcessor接口的类
		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的beanName
		List<String> orderedPostProcessorNames = new ArrayList<>();
		// 用于存放普通BeanFactoryPostProcessor的beanName
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();
		// 遍历postProcessorNames, 将BeanFactoryPostProcessor
		// 按实现PriorityOrdered、实现Ordered接口、普通三种区分开
		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.
		// [首先调用实现了PriorityOrdered的BeanFactoryPostProcessors]
		// 对priorityOrderedPostProcessors排序
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		// 遍历priorityOrderedPostProcessors, 执行postProcessBeanFactory方法
		// 调用七
		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));
		}
		//  对orderedPostProcessors排序
		sortPostProcessors(orderedPostProcessors, beanFactory);
		// 遍历orderedPostProcessors, 执行postProcessBeanFactory方法
		// 调用八
		invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory);

		// Finally, invoke all other BeanFactoryPostProcessors.
		List<BeanFactoryPostProcessor> nonOrderedPostProcessors 
				= new ArrayList<>(nonOrderedPostProcessorNames.size());
		for (String postProcessorName : nonOrderedPostProcessorNames) {
			//  获取postProcessorName对应的bean实例, 添加到nonOrderedPostProcessors, 准备执行
			nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, 
															BeanFactoryPostProcessor.class));
		}
		// 遍历nonOrderedPostProcessors, 执行postProcessBeanFactory方法
		// 调用九
		invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory);

		// Clear cached merged bean definitions since the post-processors might have
		// modified the original metadata, e.g. replacing placeholders in values...
		// [清除元数据缓存(mergedBeanDefinitions、allBeanNamesByType、singletonBeanNamesByType),
		// 因为后处理器可能已经修改了原始元数据,例如, 替换值中的占位符...]
		beanFactory.clearMetadataCache();
	}

processConfigBeanDefinitions说明

① 根据断点,我们发现,最终他会走到ConfigurationClassPostPorcessor.processConfigBeanDefinitions中

	/**
	 * Build and validate a configuration model based on the registry of
	 * [基于注册表构建和验证配置模型]
	 * {@link Configuration} classes.
	 */
	public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {

		List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
		// 获取容器中注册的所有bean的名字[5+N]
		/*
		 *	0 = "org.springframework.context.annotation.internalConfigurationAnnotationProcessor"
		 *	1 = "org.springframework.context.annotation.internalAutowiredAnnotationProcessor"
		 *	2 = "org.springframework.context.annotation.internalCommonAnnotationProcessor"
		 *	3 = "org.springframework.context.event.internalEventListenerProcessor"
		 *	4 = "org.springframework.context.event.internalEventListenerFactory"
		 *	5 = "icoAppConfig2"
		 */
		String[] candidateNames = registry.getBeanDefinitionNames();

		for (String beanName : candidateNames) {
			BeanDefinition beanDef = registry.getBeanDefinition(beanName);
			// 判断是否是Configuration类,这里其实主要看是否有
			else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, 
																			this.metadataReaderFactory)) {
				// BeanDefinitionHolder 就是一个封装
				configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
			}
		}

		// Return immediately if no @Configuration classes were found
		if (configCandidates.isEmpty()) {
			return;
		}
		// 咱们configCandidates里面就一条数据
		// 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,所以是true
		if (registry instanceof SingletonBeanRegistry) {
			sbr = (SingletonBeanRegistry) registry;
			if (!this.localBeanNameGeneratorSet) {
				BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
						AnnotationConfigUtils.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
		ConfigurationClassParser parser = new ConfigurationClassParser(
				this.metadataReaderFactory, this.problemReporter, this.environment,
				this.resourceLoader, this.componentScanBeanNameGenerator, registry);

		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
			// 这里面又是一个reader
			if (this.reader == null) {
				this.reader = new ConfigurationClassBeanDefinitionReader(
						registry, this.sourceExtractor, this.resourceLoader, this.environment,
						this.importBeanNameGenerator, parser.getImportRegistry());
			}
			this.reader.loadBeanDefinitions(configClasses);
			alreadyParsed.addAll(configClasses);

			candidates.clear();
			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();
		}
	}

checkConfigurationClassCandidate说明
	/**
	 * Check whether the given bean definition is a candidate for a configuration class
	 * (or a nested component class declared within a configuration/component class,
	 * to be auto-registered as well), and mark it accordingly.
	 * [检查给定的bean定义是否有配置类(或有声明@configuration/@component的Class,也可自动注册),并相应地标记它]
	 * 通过setAttribute标记
	 * @param beanDef the bean definition to check
	 * @param metadataReaderFactory the current factory in use by the caller
	 * @return whether the candidate qualifies as (any kind of) configuration class
	 */
	public static boolean checkConfigurationClassCandidate(
			BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {

		String className = beanDef.getBeanClassName();
		if (className == null || beanDef.getFactoryMethodName() != null) {
			return false;
		}

		AnnotationMetadata metadata;
		if (beanDef instanceof AnnotatedBeanDefinition &&
				className.equals(((AnnotatedBeanDefinition) beanDef).getMetadata().getClassName())) {
			// Can reuse the pre-parsed metadata from the given BeanDefinition...
			metadata = ((AnnotatedBeanDefinition) beanDef).getMetadata();
		}
		else if (beanDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) beanDef).hasBeanClass()) {
			// Check already loaded Class if present...
			// since we possibly can't even load the class file for this Class.
			Class<?> beanClass = ((AbstractBeanDefinition) beanDef).getBeanClass();
			// 过滤掉其他五个
			if (BeanFactoryPostProcessor.class.isAssignableFrom(beanClass) ||
					BeanPostProcessor.class.isAssignableFrom(beanClass) ||
					AopInfrastructureBean.class.isAssignableFrom(beanClass) ||
					EventListenerFactory.class.isAssignableFrom(beanClass)) {
				return false;
			}
			metadata = AnnotationMetadata.introspect(beanClass);
		}
		else {
			try {
				MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(className);
				metadata = metadataReader.getAnnotationMetadata();
			}
			catch (IOException ex) {
				if (logger.isDebugEnabled()) {
					logger.debug("Could not find class file for introspecting configuration annotations: " +
							className, ex);
				}
				return false;
			}
		}

		// 核心判断,咱们的IocTest2有Controller
		Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());
		// 如果有@Configuration
		if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
			beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
		}
		// 判断是否含有@Component、@ComponentScan、 @Import、@ImportResource这些注解
		else if (config != null || isConfigurationCandidate(metadata)) {
			beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
		}
		else {
			return false;
		}

		// It's a full or lite configuration candidate... Let's determine the order value, if any.
		Integer order = getOrder(metadata);
		if (order != null) {
			beanDef.setAttribute(ORDER_ATTRIBUTE, order);
		}

		return true;
	}

总结
  • PostProcessorRegistrationDelegate的另外一个内部方法invokeBeanDefinitionRegistryPostProcessors有两个参数,主要处理BeanDefinitionRegistryPostProcessor 接口

    • BeanDefinitionRegistryPostProcessor主要用来在BeanFactoryPostProcessor检测开始之前注册其他 Bean 定义,说的简单点,就是 BeanDefinitionRegistryPostProcessor 具有更高的优先级,执行顺序在 BeanFactoryPostProcessor 之前。通过代码也可以看出,四个invokeBeanDefinitionRegistryPostProcessors(包含第一个postProcessBeanDefinitionRegistry)方法在六个invokeBeanFactoryPostProcessors 之前被执行
  • PostProcessorRegistrationDelegate的内部方法invokeBeanFactoryPostProcessors 有两个参数

    • Collection<? extends BeanFactoryPostProcessor> postProcessors
       其中postProcessors主要有BeanDefinitionRegistryPostProcessor 和 BeanFactoryPostProcessor,他们是继承关系,增加了一个扩展接口postProcessBeanDefinitionRegistry,当前方法对两个接口都会进行处理。
    • ConfigurableListableBeanFactory beanFactory
       整个 invokeBeanFactoryPostProcessors 方法操作了 3 种 bean 对象:
      • BeanFactoryPostProcessors:是AbstractApplicationContext 类的beanFactoryPostProcessors属性值,也就是在之前已经添加到 beanFactoryPostProcessors中的BeanFactoryPostProcessor。
      • BeanDefinitionRegistryPostProcessor 接口实现类:实现了 BeanDefinitionRegistryPostProcessor 接口,并且注册到 Spring IoC容器中。
      • RegularBeanFactoryPostProcessor 接口实现类:实现了 BeanFactoryPostProcessor 接口,并且注册到 Spring IoC容器中。
  • 操作3种 bean 对象具体指的是调用它们重写的方法,调用实现方法时会遵循以下的优先级:

    • 第一优先级:入参 beanFactoryPostProcessors 中的 BeanDefinitionRegistryPostProcessor, 调用 postProcessBeanDefinitionRegistry 方法(调用一)。
    • 第二优先级:BeanDefinitionRegistryPostProcessor 接口实现类,并且实现了 PriorityOrdered 接口,调用 postProcessBeanDefinitionRegistry 方法(调用二)。
    • 第三优先级:BeanDefinitionRegistryPostProcessor 接口实现类,并且实现了 Ordered 接口,调用 postProcessBeanDefinitionRegistry 方法(调用三)。
    • 第四优先级:除去第二优先级和第三优先级,剩余的 BeanDefinitionRegistryPostProcessor 接口实现类,调用 postProcessBeanDefinitionRegistry 方法(调用四)。
    • 第五优先级:所有 BeanDefinitionRegistryPostProcessor 接口实现类,调用 postProcessBeanFactory 方法(调用五)。
    • 第六优先级:入参 beanFactoryPostProcessors 中的常规 BeanFactoryPostProcessor,调用 postProcessBeanFactory 方法(调用六)。
    • 第七优先级:常规 BeanFactoryPostProcessor 接口实现类,并且实现了 PriorityOrdered 接口,调用 postProcessBeanFactory 方法(调用七)。
    • 第八优先级:常规 BeanFactoryPostProcessor 接口实现类,并且实现了 Ordered 接口,调用 postProcessBeanFactory 方法(调用八)。
    • 第九优先级:除去第七优先级和第八优先级,剩余的常规 BeanFactoryPostProcessor 接口的实现类,调用 postProcessBeanFactory 方法(调用九)。

由于当前例子中没有充分体现整个执行过程,后续会优化测试用例重新执行过一遍代码

未完待续。。

参考:
https://blog.csdn.net/v123411739/article/details/87741251
还有子路

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值