AbstractApplicationContext.refresh()应用上下文刷新方法分析

前情提要: 学习源码光看博客文章基本没有记住的可能.结合源码和博客+实践才能够通过理解记住,看了很多天才断断续续看完,发现它和其他IOC、Bean生命周期都有关联,将之前片段式的认知串联起来了.

这个刷新的代码很长,建议没耐心的时候就先不看,但是每天固定一个时间看一会,熟练了再串联起来看一遍.
其他关联文章

Spring控制反转IOC和依赖注入DI结构化简述
Springboot自动装配及实现
Spring循环依赖和三级缓存解决方案介绍
BeanFactory和FactoryBean区别
SpringApplication上下文刷新第五步invokeBeanFactoryPostProcessors
SpringApplication上下文刷新第六步registerBeanPostProcessors
SpringApplication上下文刷新第十一步finishBeanFactoryInitialization
SpringApplication上下文刷新之Bean创建
流程分明的Spring的Bean生命周期

上下文刷新方法被调用时机是SpringBoot.run启动中上下文准备方法(prepareContext)执行完毕后进行同步调用的

上下文准备方法(prepareContext)主要执行SpringApplication初始化时加载的上下文初始化器,以及发布上下文准备完毕事件,关闭启动上下文,发布上下文初始化完毕事件
private void refreshContext(ConfigurableApplicationContext context) {
	if (this.registerShutdownHook) {
		try {
		    // 注册停止钩子(停止执行的线程),当JVM准备停止时执行,自定义钩子优先级最高 -->Runtime.getRuntime().addShutdownHook(Thread hook);
		    // 会发布ContextClosedEvent事件
		    // 销毁所有Bean(删除容器中的Bean,执行Bean的destory方法)
			context.registerShutdownHook();
		}
		catch (AccessControlException ex) {
			// Not allowed in some environments.
		}
	}
	// 该方法会一直调用到AbstractApplicationContext.refresh方法.中间大多是参数校验和直接调用
	refresh((ApplicationContext) context);
}

refresh方法本体解析

public void refresh() throws BeansException, IllegalStateException {
	synchronized (this.startupShutdownMonitor) {
	    // 忽略掉不重要!启动阶段标记,初始化时标记位为false,执行refresh完毕后修改为true(最后的end方法).
		StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

		// 1. 准备刷新上下文方法,用于设置准备刷新前的一些参数:
		//  程序启动标志位/上下文拓展资源加载/上下文环境准备情况验证/监听器监听事件容器初始化准备
		prepareRefresh();

		// 2. 获取BeanFactory,内部调用refreshBeanFactory()和getBeanFactory()均由子类实现
		//  告知子类刷新Bean工厂(设置序列号ID--> 参考GenericApplicationContext)
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

		// 3. 初始化Bean工厂,设置基础属性: ClassLoader、SPEL(SPring表达式)解析器、属性编辑器(自定义属性覆盖默认属性)、
		//  添加系统BeanPostProcessor`ResourceEditorRegistrar(初始化前执行一些Aware即invokeAwareInterfaces方法)`、
		//  忽略一些系统级接口装配依赖、注入一些不能自动创建的Bean依赖(Bean工厂,ResourceLoader(加载资源文件),事件发布类,上下文)、
		//  加系统BeanPostProcessor`ApplicationListenerDetector(Bean初始化后执行,判断是否是单例监听器加到上下文中)`、
		//  加入AspectJ静态代理支持、系统环境Bean检查注册
		prepareBeanFactory(beanFactory);

		try {
			// 4. BeanFactory配置好的后置拓展操作.由子类拓展.可在这里提前加入自定义BeanFactoryPostProcess
			postProcessBeanFactory(beanFactory);

            // 忽略掉不重要!启动阶段标记
			StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
			// 5. 执行BeanFactory后置处理. Spring的SPI机制保障(可看我自动装载文章).
			invokeBeanFactoryPostProcessors(beanFactory);

			// 6. 注册BeanPostProcessors到BeanFacotry中并排序,并未执行.涉及到Bean生命周期执行
			registerBeanPostProcessors(beanFactory);
			beanPostProcess.end();

			// 7. 初始化MessageSource,用于消息国际化处理
			initMessageSource();

			// 8. 初始化上下文事件广播器
			initApplicationEventMulticaster();

			// 9. 子类实现,springbootstarterweb在此创建web容器,并提前生成容器所需的Bean及其对应生命周期
			onRefresh();

			// 10. 给广播器中注册监听器,执行初期事件
			registerListeners();

			// 11. 初始化所有非懒加载单例Bean
			finishBeanFactoryInitialization(beanFactory);

			// 12. 完成刷新,发布上下文刷新完毕事件
			finishRefresh();
		}catch (BeansException ex) {
			if (logger.isWarnEnabled()) {
				logger.warn("Exception encountered during context initialization - " +
						"cancelling refresh attempt: " + ex);
			}
			// 刷新异常,销毁已经创建的Bean
			destroyBeans();
			// 取消刷新,设置active为false
			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();
			// 刷新结束,设置标志位为true
			contextRefresh.end();
		}
	}
}

1. 准备刷新上下文方法

	protected void prepareRefresh() {
		// 设置基础属性,设置当前状态为活跃/启动
		this.startupDate = System.currentTimeMillis();
		this.closed.set(false);
		this.active.set(true);
        // log打印

		// 交由子类实现,用于加载初始化资源属性.
		initPropertySources();

		// 校验所需要的环境变量是否已经加载进来
		getEnvironment().validateRequiredProperties();

		// 保留未生成Context时加载的Linsteners监听器
		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);
		}

		// 创建ApplicationEvent监听事件容器
		this.earlyApplicationEvents = new LinkedHashSet<>();
	}

2. 获取BeanFactory

这两个方法均交由子类实现,大致是设置BeanFactory序列化ID号.参考AnnotationConfigServletWebServerApplicationContext类的父类GenericApplicationContext类

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

3. 初始化Bean工厂各种属性和容器内容

protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
	// 设置BeanFactory的ClassLoader
	beanFactory.setBeanClassLoader(getClassLoader());
	// 判断是否需要加载Spring-Spel表达式解析器.默认加载
	if (!shouldIgnoreSpel) {
		beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
	}
	// 添加属性编辑器用于自定义属性设置覆盖
	beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

	// 添加默认注册Bean前加入BeanPostProcessor用于Bean初始化前进行操作: 如果Bean实现了某个Aware则调用对应方法.可查看ApplicationContextAwareProcessor.ApplicationContextAwareProcessor方法,自定义Bean可进行拓展
	beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
	// 忽略一些系统级接口依赖,这些方法在上面的Processor中检查回调中会执行.
	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.ignoreDependencyInterface(ApplicationStartup.class);

	// 设置注册不能自动创建的Bean依赖
	beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
	beanFactory.registerResolvableDependency(ResourceLoader.class, this);
	beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
	beanFactory.registerResolvableDependency(ApplicationContext.class, this);

	// 添加Bean初始化后操作,如果有该单例监听器Bean就加入到上下文监听器容器中
	beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

	// 加入AspectJ支持(静态代理,启动时会改变被代理类字节码进行增强https://blog.csdn.net/crazyzhb2012/article/details/53827540 | https://developer.aliyun.com/article/574571)
	if (!NativeDetector.inNativeImage() && 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()));
	}

	// 检查并加入一些默认的初始化环境Bean
	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());
	}
	if (!beanFactory.containsLocalBean(APPLICATION_STARTUP_BEAN_NAME)) {
		beanFactory.registerSingleton(APPLICATION_STARTUP_BEAN_NAME, getApplicationStartup());
	}
}

4. BeanFactory配置好的后置拓展操作

作为BeanFactory设置好后Bean加载初始化前拓展扫描/的后置操作(Web服务查看AnnotationConfigServletWebServerApplicationContext,加入了一个BeanPostProcess,不过实际没有作用)

// ServletWebServerApplicationContext中的方法
protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
	beanFactory.addBeanPostProcessor(new WebApplicationContextServletContextAwareProcessor(this));
	beanFactory.ignoreDependencyInterface(ServletContextAware.class);
	// 最主要是最后这步,为BeanFactory注册了request、session的web域
	// 并注册了ServletRequest、ServletResponse、HttpSession、WebRequest到容器中
	registerWebApplicationScopes();
}

5. 执行BeanFactory后置处理.

invokeBeanFactoryPostProcessors方法比较长,但是很容易懂,放到这个博客中了.在此步Spring扫描加载完毕所有的BeanDefinition(扫描出来的各种注解和config配置的Bean定义).然后执行所有postProcessBeanDefinitionRegistry方法和postProcessBeanFactory方法

protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
    // 调用执行默认的和自定义的BeanDefinitionRegistryPostProcessor和BeanFactoryPostProcessor类方法
	PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(beanFactory, getBeanFactoryPostProcessors());
	//···其他
}

6. 注册BeanPostProcessors到BeanFacotry中并排序,并未执行.涉及到.涉及到Bean生命周期执行

registerBeanPostProcessors方法比较长,但是很容易懂,放到这个博客中了.
涉及到的Bean生命周期可查看Spring控制反转IOC和依赖注入DI结构化简述流程分明的Spring的Bean生命周期

protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
	PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}

7. 初始化一个MessageSource.用于消息国际化、参数化

Spring 两个开箱即用的实现 ResourceBundleMessageSource 和 ReloadableResourceBundleMessageSource

protected void initMessageSource() {
	ConfigurableListableBeanFactory beanFactory = getBeanFactory();
	if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
		this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
		// Make MessageSource aware of parent MessageSource.
		if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
			HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
			if (hms.getParentMessageSource() == null) {
				// Only set parent context as parent MessageSource if no parent MessageSource
				// registered already.
				hms.setParentMessageSource(getInternalParentMessageSource());
			}
		}
		if (logger.isTraceEnabled()) {
			logger.trace("Using MessageSource [" + this.messageSource + "]");
		}
	}
	else {
		// Use empty MessageSource to be able to accept getMessage calls.
		DelegatingMessageSource dms = new DelegatingMessageSource();
		dms.setParentMessageSource(getInternalParentMessageSource());
		this.messageSource = dms;
		beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
		if (logger.isTraceEnabled()) {
			logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");
		}
	}
}

8. 初始化上下文事件广播器

事件广播器用于Spring事件通知机制,监听器通过指定监听事件,当广播器广播该事件时会执行对应监听器方法.
该方法表示如果有自定义广播器则使用自定义广播器没有则创建一个SimpleApplicationEventMulticaster.可自定义拓展让广播器监听事件异步执行
保存事件和对应监听器列表映射,发布事件后会找到该事件的所有监听器.如果由线程池则异步执行.没有则同步执行

protected void initApplicationEventMulticaster() {
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    // 如果用户手动新建了一个名为applicationEventMulticaster类型为ApplicationEventMulticaster的bean,则将这个bean作为事件广播器
    if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) {
        this.applicationEventMulticaster =
                beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class);
    }
    else {
        // 否则新建一个SimpleApplicationEventMulticaster作为默认的事件广播器
        this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory);
        beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster);
    }
}

9. springbootstarterweb在此创建web容器

查看AnnotationConfigServletWebServerApplicationContext的父类ServletWebServerApplicationContext.在这一步创建了Tomcate服务器,初始化各种web组件

private void createWebServer() {
	WebServer webServer = this.webServer;
	ServletContext servletContext = getServletContext();
	if (webServer == null && servletContext == null) {
		StartupStep createWebServer = this.getApplicationStartup().start("spring.boot.webserver.create");
		ServletWebServerFactory factory = getWebServerFactory();
		createWebServer.tag("factory", factory.getClass().toString());
		// 创建web服务器并初始化各种MVC组件
		this.webServer = factory.getWebServer(getSelfInitializer());
		createWebServer.end();
		getBeanFactory().registerSingleton("webServerGracefulShutdown",
				new WebServerGracefulShutdownLifecycle(this.webServer));
		getBeanFactory().registerSingleton("webServerStartStop",
				new WebServerStartStopLifecycle(this, this.webServer));
	}
	else if (servletContext != null) {
		try {
			getSelfInitializer().onStartup(servletContext);
		}
		catch (ServletException ex) {
			throw new ApplicationContextException("Cannot initialize servlet context", ex);
		}
	}
	initPropertySources();
}

10. 给广播器中注册监听器,发布广播器未初始化时加载的事件

将早期加入的系统监听器加入广播器中.常规的监听器Bean则先加入名字等到后面和其他Bean一起创建.从BeanFactory中获取即可.并发布早期Application事件

protected void registerListeners() {
	// 将Application启动时加载的Linsteners加入广播器中
	for (ApplicationListener<?> listener : getApplicationListeners()) {
		getApplicationEventMulticaster().addApplicationListener(listener);
	}

	// 先将常规的监听器Bean名称放入,后续再创建
	String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false);
	for (String listenerBeanName : listenerBeanNames) {
		getApplicationEventMulticaster().addApplicationListenerBean(listenerBeanName);
	}

	// 早期Application事件发布
	Set<ApplicationEvent> earlyEventsToProcess = this.earlyApplicationEvents;
	this.earlyApplicationEvents = null;
	if (!CollectionUtils.isEmpty(earlyEventsToProcess)) {
		for (ApplicationEvent earlyEvent : earlyEventsToProcess) {
			getApplicationEventMulticaster().multicastEvent(earlyEvent);
		}
	}
}

11. 初始化所有非懒加载单例Bean

该步骤如果有类型转换Bean则添加自定义的类型转换Bean
在加载单例Bean前提前加入了为AOP切入点织入通知的Bean
关闭临时类加载器,设置冻结BeanDefinition标志为true,不允许Bean生成前再修改Bean了
最后进行Bean加载.比较长放到finishBeanFactoryInitialization讲解文章Bean创建文章

12. 完成刷新,发布上下文刷新完毕事件

  1. 加载LifecycleProcessor.执行其刷新方法.会将实现了SmartLifecycle接口的Bean加入Application生命周期,启动时执行start方法,关闭时执行stop方法,可以启动一些监控组件之类的东西.
  2. 发布上下文刷新事件
protected void finishRefresh() {
	// 清除为上下文创建初始化准备的资源文件数据信息缓存.比如ASM的元数据信息
	clearResourceCaches();

	// 一般是加载DefaultLifecycleProcessor
	initLifecycleProcessor();

	// 执行生命周期处理器的onRefresh方法.会调用实现了SmartLifecycle接口的start方法启动对应Bean生命周期(随着Application启动启动,关闭而关闭)
	getLifecycleProcessor().onRefresh();

	// 发布上下文刷新完毕事件
	publishEvent(new ContextRefreshedEvent(this));

	// 设置JMX则执行
	if (!NativeDetector.inNativeImage()) {
		LiveBeansView.registerApplicationContext(this);
	}
}

protected void initLifecycleProcessor() {
	ConfigurableListableBeanFactory beanFactory = getBeanFactory();
	// 我们自己没定义就一定是走下面默认的LifecycleProcssor上.我们自己定义的话最好也是继承下面那个默认的来定义,下面那个默认的是让Bean生命周期随上下文一致的保证.
	if (beanFactory.containsLocalBean(LIFECYCLE_PROCESSOR_BEAN_NAME)) {
		this.lifecycleProcessor =
				beanFactory.getBean(LIFECYCLE_PROCESSOR_BEAN_NAME, LifecycleProcessor.class);
		if (logger.isTraceEnabled()) {
			logger.trace("Using LifecycleProcessor [" + this.lifecycleProcessor + "]");
		}
	}
	else {
		DefaultLifecycleProcessor defaultProcessor = new DefaultLifecycleProcessor();
		defaultProcessor.setBeanFactory(beanFactory);
		this.lifecycleProcessor = defaultProcessor;
		beanFactory.registerSingleton(LIFECYCLE_PROCESSOR_BEAN_NAME, this.lifecycleProcessor);
		if (logger.isTraceEnabled()) {
			logger.trace("No '" + LIFECYCLE_PROCESSOR_BEAN_NAME + "' bean, using " +
					"[" + this.lifecycleProcessor.getClass().getSimpleName() + "]");
		}
	}
}

DefaultLifecycleProcessor的刷新启动Bean周期方法
关闭就是执行SmartLifecycle的stop方法就不展示了

public void onRefresh() {
	startBeans(true);
	this.running = true;
}
// 找出所有实现SmartLifecycle并且声明为自动启动的Bean执行启动方法
private void startBeans(boolean autoStartupOnly) {
	Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
	Map<Integer, LifecycleGroup> phases = new TreeMap<>();

	lifecycleBeans.forEach((beanName, bean) -> {
		if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
			int phase = getPhase(bean);
			phases.computeIfAbsent(
					phase,
					p -> new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly)
			).add(beanName, bean);
		}
	});
	if (!phases.isEmpty()) {
		phases.values().forEach(LifecycleGroup::start);
	}
}

最后还有几个Spring上下文的内置事件ContextRefreshedEvent(ApplicationContext 被初始化或刷新时)、ContextStartedEvent、ContextStoppedEvent、ContextClosedEvent、RequestHandledEvent可以进行拓展

参考

spring学习之源码分析–AbstractApplicationContext之refresh
Spring Event事件通知机制
Spring Boot 中 Tomcat 是怎么启动的
Spring IOC容器启动流程 AbstractApplicationContext#refresh()方法源码分析
SpringMVC之类型转换Converter
Spring支持的转换器 示例 使用ConversionService转换数据

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值