IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 当我们在聊 IoC 的时候,我们来聊聊 refresh() ?(中篇) -> 正文阅读

[Java知识库]当我们在聊 IoC 的时候,我们来聊聊 refresh() ?(中篇)

当我们在聊 IoC 的时候,我们来聊聊 refresh() ?(中篇)

书接上文:

	/**
	 * Create a new AnnotationConfigApplicationContext, deriving bean definitions
	 * from the given component classes and automatically refreshing the context.
	 * @param componentClasses one or more component classes — for example,
	 * {@link Configuration @Configuration} classes
	 */
	public AnnotationConfigApplicationContext(Class<?>... componentClasses) {
		this();
		register(componentClasses);
		refresh();
	}

上篇 当我们在聊 IoC 的时候,我们在聊什么?(上篇) 我们从 AnnotationConfigApplicationContext 这个类入手,对 Spring IoC 容器的整个加载过程做一个全面的剖析,本文将详细介绍这里最最核心的一个方法 refresh() 方法,这个方法是我们要重点记忆的。

在介绍 refresh() 方法之前,首先回顾一下上面的流程:

  1. this() 方法调用无参构造函数,并且调用父类的构造方法,初始化了 BeanDefinitionReaderBeanDefinitionScanner 在初始化 BeanDefinitionReader 的时候 Spring 同时将 系统内置的 BeanFactoryPostProcessor注册到了 BeanDefinition 当中(即存放到了对应的 Map)这里为之后的用户配置类的扫描和读取打下基础。
  2. register(componentClasses)注册用户传入的配置类的 BeanDefinitionBeanDefinitionMap

在这里插入图片描述

那么 refresh 又做了什么?

refresh() 方法

首先一点,对于源码,我们没有必要事无巨细的扣每一行语句,除非你想改他的源码或者是其相关开发人员(这类大佬应该不用看我这篇文章了吧,挠头),否则过度的解读源码只会让你深陷其中不得要领,我们需要的是抓住其重点的方法进行解读,而边角的逻辑是需要我们进行一定的忽略的,就比如你在开发的时候通用会做很多边界值的判断以及一些异常 case 的处理,但是这些处理其实对你理解主逻辑是没有帮助的,尤其是你在不了解其内在运行机制的时候很可能就被一句边界 case 处理绕晕了。所以本文会抓住重点的方法进行罗列,而其他的分支或者低优先级的方法不会过度深究。

在这里插入图片描述

以上就是 refresh 中的所有调用方法,对一些方法做了简单的功能描述,这里我们重点关注其中的三个方法:

// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);

// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);

// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);

首先是 invokeBeanFactoryPostProcessors(beanFactory)

该方法初始化并调用了在上下文中注册的那些 BeanFactoryPostProcessor 这些包含了 Spring 的系统内置的后置处理器,这些后置处理器将会对我们的 Bean 进行扫描和注册。从这里也可以看出,Spring 自身的实现也是通过这些扩展点来进行的,而我们的一些插件或者开发也可以利用 Spring 提供的扩展点进行自己的定制。

/**
 * Instantiate and invoke all registered BeanFactoryPostProcessor beans,
 * respecting explicit order if given.
 * <p>Must be called before singleton instantiation.
 */
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 (!NativeDetector.inNativeImage() && beanFactory.getTempClassLoader() == null && beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
		beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
		beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
	}
}

这里调用的是 PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors()) 的方法,这里列出几个关键的代码,感兴趣的同学可以自行查看源码

首先是实例化并调用实现了 PriorityOrdered 接口的 BeanDefinitionRegistryPostProcessor 后置处理器中的方法

List<BeanDefinitionRegistryPostProcessor> registryProcessors = new ArrayList<>();
// First, invoke the BeanDefinitionRegistryPostProcessors that implement PriorityOrdered.
// 获取所有实现了 BeanDefinitionRegistryPostProcessor 接口的类名
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false);
// 首先会调用实现了 PriorityOrdered 接口的后置处理器
for (String ppName : postProcessorNames) {
	if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
    // 这里调用了 beanFactory.getBean 方法实例化了 bean
		currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));
		processedBeans.add(ppName);
	}
}
// 排序后置处理器
sortPostProcessors(currentRegistryProcessors, beanFactory);
// 将 currentRegistryProcessors 全部添加到 registryProcessors 中
registryProcessors.addAll(currentRegistryProcessors);
// 这里调用了实现 BeanDefinitionRegistryPostProcessor 接口的 postProcessBeanDefinitionRegistry 方法
invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();

然后是实现了 Ordered 接口的,套路同上

// 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, beanFactory.getApplicationStartup());
currentRegistryProcessors.clear();

最后调用其他的 BeanDefinitionRegistryPostProcessors

// 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, beanFactory.getApplicationStartup());
	currentRegistryProcessors.clear();
}

这里是调用完了 BeanDefinitionRegistryPostProcessorpostProcessBeanDefinitionRegistry 方法,也就是说先调用 BeanDefinitionRegistry 的后置处理器,然后再调用 BeanFactoryPostProcessorpostProcessBeanFactory 方法,也就是 BeanFactory 的后置处理器

看一眼继承关系,也就是说实现了 BeanDefinitionRegistryPostProcessor 的同时也会实现 BeanFactoryPostProcessor

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {

	/**
	 * Modify the application context's internal bean definition registry after its
	 * standard initialization. All regular bean definitions will have been loaded,
	 * but no beans will have been instantiated yet. This allows for adding further
	 * bean definitions before the next post-processing phase kicks in.
	 * @param registry the bean definition registry used by the application context
	 * @throws org.springframework.beans.BeansException in case of errors
	 */
	void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;

}

这里调用所有上述的 registryProcessorspostProcessBeanFactory() 方法,以及常规的 regularPostProcessors 也就是仅实现了BeanFactoryPostProcessor 接口的类。

// Now, invoke the postProcessBeanFactory callback of all processors handled so far.
invokeBeanFactoryPostProcessors(registryProcessors, beanFactory);
invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory);

后面是获取所有实现了 BeanFactoryPostProcessor 的类并调用其后置处理方法,同样的也处理了排序的优先级

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

回过头来看看,在初始化 registry 的时候注册的系统的后置处理器都做了什么:

首先是 ConfigurationClassPostProcessor implements BeanDefinitionRegistryPostProcessor

	/**
	 * Derive further bean definitions from the configuration classes in the registry.
	 */
	@Override
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
		int registryId = System.identityHashCode(registry);
		if (this.registriesPostProcessed.contains(registryId)) {
			throw new IllegalStateException(
					"postProcessBeanDefinitionRegistry already called on this post-processor against " + registry);
		}
		if (this.factoriesPostProcessed.contains(registryId)) {
			throw new IllegalStateException(
					"postProcessBeanFactory already called on this post-processor against " + registry);
		}
		this.registriesPostProcessed.add(registryId);

		processConfigBeanDefinitions(registry);
	}

这个后置处理器会将我们配置带有 @Configuration 注解的类进行注册

processConfigBeanDefinitions(registry);

该方法中的 ConfigurationClassParser 将会注册我们所有带有 @Configuration 注解的类

// Parse each @Configuration class
ConfigurationClassParser parser = new ConfigurationClassParser(
				this.metadataReaderFactory, this.problemReporter, this.environment,
				this.resourceLoader, this.componentScanBeanNameGenerator, registry);
parser.parse(candidates);

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CFlDw7hH-1636882749426)(/Users/admin/Library/Application Support/typora-user-images/image-20211114171349566.png)]

如上图可以看到注册了我定义的 TestConfiguration 测试类

invokeBeanFactoryPostProcessors(beanFactory) 方法到此结束。

// 有序调用 BeanDefinitionRegistryPostProcessor 方法以及 BeanFactoryPostProcessor 
// 重要一点是调用了系统内置的 ConfigurationClassPostProcessor 加载带有 @Configuration 的 bean 到 bean 定义中
invokeBeanFactoryPostProcessors(beanFactory);

// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);

// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);

因为篇幅问题,refresh() 方法先介绍到这里,剩余的部分放到下篇。

这里是 dying 搁浅,我们下篇再见。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-11-15 15:42:36  更:2021-11-15 15:43:52 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 2:53:47-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码