Spring IOC(二): refresh 分析 prepare过程

本文继续跟着上一篇文章走,开始分析 AbstractApplicationrefresh 方法。

本文主要围绕以下几个方面进行:

加锁

AbstractApplication 中,定义了 Object 类型的 变量 startupShutdownMonitor 作为锁。当执行 refresh 和 destroy 方法则会进行加锁禁止并发操作。

synchronized (this.startupShutdownMonitor) {
   ... 
}

prepareRefresh

该方法,主要是为refresh 方法执行 准备操作。

	protected void prepareRefresh() {
		// 设置启动日期,closed 和 active 状态
		this.startupDate = System.currentTimeMillis();
		this.closed.set(false);
		this.active.set(true);
		// log 打日志
		if (logger.isDebugEnabled()) {
			if (logger.isTraceEnabled()) {
				logger.trace("Refreshing " + this);
			}
			else {
				logger.debug("Refreshing " + getDisplayName());
			}
		}
		// 初始化 一些环境变量信息,由子类实现。
		initPropertySources();
		// 验证所有变量的合法性
		getEnvironment().validateRequiredProperties();
		// 存储 pre-refresh 类型的 ApplicationListeners
		if (this.earlyApplicationListeners == null) {
			this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
		}
		else {
			// Reset local application listeners to pre-refresh state.
			this.applicationListeners.clear();
			this.applicationListeners.addAll(this.earlyApplicationListeners);
		}
		// 初始化 early ApplicationEvents 类型的事件,允许 multicaster 可用时立刻触发。
		this.earlyApplicationEvents = new LinkedHashSet<>();
	}

以上几步主要是初始化 资源,例如 earlyApplicationListenersapplicationListenersearlyApplicationEvents
另一方面,也会使用 initPropertySources去加载子类所需要的一些 属性。
validateRequiredProperties 则是对属性进行验证。
例如,如果项目项目里面使用了 某一个环境变量,而 对应机器或者 在 initPropertySources 加载资源未加载进去,则可以在 validateRequiredProperties 验证不通过进行告警。

obtainFreshBeanFactory

在这里面主要是让子类去刷新(refresh) beanFactory。

obtainFreshBeanFactory:

	protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
		refreshBeanFactory();
		return getBeanFactory();
	}

refreshBeanFactory 是 protected 的空方法,主要看子类如何实现。

本文使用 是 AnnotationConfigApplicationContext
在这里插入图片描述

在 当前类 AnnotationConfigApplicationContext 中,并没有 实现 refreshBeanFactory,而在 其父类 GenericApplication 中有实现该方法,并在 在GenericApplication 中会对 final 成员变量 beanFactory 进行初始化。默认构造为 DefaultListableBeanFactory
GenericApplicationContextrefreshBeanFactory

	@Override
	protected final void refreshBeanFactory() throws IllegalStateException {
		if (!this.refreshed.compareAndSet(false, true)) {
			throw new IllegalStateException(
					"GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
		}
		this.beanFactory.setSerializationId(getId());
	}

里面判断了 beanFactory 初始化状态,以及设置 了 beanFactory 的序列化id。
在这里插入图片描述

prepareBeanFactory

准备完环境,初始化了BeanFactory,那么到这里就开始要为使用BeanFactory做准备了。

	protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
		// Tell the internal bean factory to use the context's class loader etc.
		beanFactory.setBeanClassLoader(getClassLoader());
		beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
		beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

		// Configure the bean factory with context callbacks.
		beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
		beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
		beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
		beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
		beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
		beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

		// BeanFactory interface not registered as resolvable type in a plain factory.
		// MessageSource registered (and found for autowiring) as a bean.
		beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
		beanFactory.registerResolvableDependency(ResourceLoader.class, this);
		beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
		beanFactory.registerResolvableDependency(ApplicationContext.class, this);

		// Register early post-processor for detecting inner beans as ApplicationListeners.
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

		// Detect a LoadTimeWeaver and prepare for weaving, if found.
		if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
			beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
			// Set a temporary ClassLoader for type matching.
			beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
		}

		// Register default environment beans.
		if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
			beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
		}
		if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
			beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
		}
		if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
			beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
		}
	}

上文准备过程,包括添加classLoader,忽略了一些DependencyInterface(这些不需要bean初始化),还添加了两个BeanPostProcessor

  1. ApplicationContextAwareProcessor: 用于在初始化bean时候,自动填入一些属性。
  2. ApplicationListenerDetector: 添加ApplicationListeners 所需要的支持。

后面则根据需要提前注册了一些bean。

觉得博主写的有用,不妨关注博主公众号: 六点A君。
哈哈哈,一起研究Spring:
在这里插入图片描述

<think>好的,我需要回答用户关于Spring 6中refresh机制的工作原理,并且通过图解说明的问题。首先,我需要回顾Spring框架中ApplicationContext的refresh机制的基本概念。根据引用[3],ApplicationContext是Spring IOC容器,负责实例化、配置和组装bean。refresh机制是容器初始化和刷新的核心流程。 接下来,我需要确认Spring 6中是否有关于refresh机制的更新或改进。由于用户提到的是Spring 6,而引用中的内容可能来自较早版本,我需要假设用户可能关注的是核心流程是否有变化。不过,通常核心机制如refresh在版本迭代中保持相对稳定,可能会有优化而不是根本性改变。 然后,我需要分解refresh机制的具体步骤。根据常见的Spring ApplicationContext生命周期,refresh过程包括以下几个关键步骤: 1. 准备刷新(Prepare refresh):设置启动时间、活跃标志,初始化属性源等。 2. 获取BeanFactory(Obtain fresh BeanFactory):例如,GenericApplicationContext会创建内部BeanFactory实例。 3. BeanFactory预处理(Post-process BeanFactory):例如,配置类处理、添加BeanPostProcessor等。 4. 调用BeanFactoryPostProcessors(Invoke BeanFactory post-processors):处理配置类的解析,如@ComponentScan、@Import等。 5. 注册BeanPostProcessors(Register Bean post-processors):注册拦截Bean创建过程的处理器。 6. 初始化消息源(Init MessageSource):国际化支持。 7. 初始化事件广播器(Init ApplicationEventMulticaster):用于事件发布。 8. 初始化特殊Bean(On refresh):例如,创建Web服务器等(在Spring Boot中常见)。 9. 注册监听器(Register listeners):注册应用事件监听器。 10. 完成BeanFactory初始化(Finish BeanFactory initialization):实例化所有非懒加载的单例Bean。 11. 完成刷新(Finish refresh):发布ContextRefreshedEvent,完成启动过程。 用户需要图解说明,因此可能需要用文字描述各个步骤的流程,并指出每个步骤涉及的关键类或方法。例如,在准备刷新阶段,AbstractApplicationContext的prepareRefresh()方法会被调用。获取BeanFactory可能涉及refreshBeanFactory()方法,如在GenericApplicationContext中的实现。 需要确保引用中的内容是否与这些步骤相关。例如,引用[3]提到配置元数据可以通过XML、注解或Java代码表示,这可能与BeanFactoryPostProcessors处理配置元数据的步骤相关。而引用[4]中的端点添加可能涉及到Bean的注册和初始化阶段。 此外,用户提到的图解可能需要用文字模拟结构图,例如使用步骤列表和箭头表示流程。例如: 1. 准备刷新 → 2. 获取BeanFactory → 3. BeanFactory预处理 → ... → 11. 完成刷新。 在每个步骤中,可以简要说明涉及的Spring内部类或方法,如AbstractApplicationContext、BeanFactoryPostProcessor等。 需要注意的是,用户可能希望了解refresh机制在Spring Boot中的应用,比如在启动时的触发点。例如,Spring Boot的SpringApplication.run()会调用refreshContext(),最终触发ApplicationContext的refresh()方法。引用[4]中的@SpringBootApplication和@RestController可能涉及到在refresh过程中Bean的扫描和注册。 最后,要确保回答结构清晰,分步骤解释,并在适当的地方引用提供的参考资料。例如,在讲解BeanFactory预处理时,可以引用[3]中提到的配置元数据的处理过程。</think>### Spring 6 Refresh机制的工作原理 Spring的`ApplicationContext`刷新(`refresh()`)机制是IOC容器初始化和更新的核心流程。以下是其关键步骤的分解及图解说明: --- #### **1. 准备刷新(Prepare Refresh)** - **功能**:初始化上下文状态,验证环境配置。 - **关键操作**:设置启动时间、激活标志,检查必需属性[^3]。 - **代码入口**:`AbstractApplicationContext.prepareRefresh()` --- #### **2. 获取BeanFactory(Obtain Fresh BeanFactory)** - **功能**:创建或刷新内部的`BeanFactory`实例。 - **关键操作**:`GenericApplicationContext`会初始化默认的`DefaultListableBeanFactory`。 - **代码入口**:`AbstractApplicationContext.refreshBeanFactory()` --- #### **3. BeanFactory预处理(Post-Process BeanFactory)** - **功能**:配置`BeanFactory`的基础能力。 - **关键操作**: - 添加`BeanPostProcessor`(如`AutowiredAnnotationBeanPostProcessor`)。 - 注册配置类解析器(用于处理`@ComponentScan`、`@Import`等注解)。 - **代码入口**:`PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors()` --- #### **4. 调用BeanFactoryPostProcessors** - **功能**:处理配置元数据(如XML、Java注解)。 - **关键操作**: - 解析`@Configuration`类并注册Bean定义。 - 加载属性文件(如`@PropertySource`)。 - **示例**:`ConfigurationClassPostProcessor`处理配置类。 --- #### **5. 注册BeanPostProcessors** - **功能**:注册拦截Bean生命周期的处理器。 - **关键操作**:收集所有`BeanPostProcessor`并排序(如优先级排序)。 - **作用**:支持依赖注入(`@Autowired`)、AOP代理等[^1]。 --- #### **6. 初始化消息源与事件广播器** - **消息源(Init MessageSource)**:国际化支持(如`ResourceBundleMessageSource`)。 - **事件广播器(Init ApplicationEventMulticaster)**:用于发布事件(如`ContextRefreshedEvent`)。 --- #### **7. 初始化特殊Bean(On Refresh)** - **功能**:实例化与特定环境相关的Bean。 - **Spring Boot中的应用**:创建内嵌Web服务器(如Tomcat)[^4]。 --- #### **8. 注册监听器(Register Listeners)** - **功能**:将`ApplicationListener`注册到事件广播器。 - **示例**:监听`ContextRefreshedEvent`以执行启动后逻辑。 --- #### **9. 完成BeanFactory初始化(Finish BeanFactory Initialization)** - **功能**:实例化所有非懒加载的单例Bean。 - **关键操作**:调用`BeanFactory.preInstantiateSingletons()`。 --- #### **10. 完成刷新(Finish Refresh)** - **功能**:发布`ContextRefreshedEvent`,标志容器就绪。 - **Spring Boot中的触发**:通过`SpringApplication.run()`调用`refreshContext()`。 --- ### **图解流程** ```plaintext 1. 准备刷新 → 2. 获取BeanFactory → 3. BeanFactory预处理 → 4. 调用BeanFactoryPostProcessors ↓ 5. 注册BeanPostProcessors → 6. 初始化消息源/事件广播器 → 7. 初始化特殊Bean ↓ 8. 注册监听器 → 9. 完成Bean初始化 → 10. 完成刷新(发布事件) ``` --- ### **关键引用说明** - **BeanFactory配置**:配置元数据通过XML、注解或代码定义,由`BeanFactoryPostProcessor`解析。 - **事件机制**:`ApplicationEventMulticaster`处理事件发布与监听[^3]。 - **Spring Boot集成**:`@SpringBootApplication`触发`refresh()`以启动Web服务。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值