Spring核心技术-启动流程

  Spring核心技术目录

Spring启动入口

  启动入口为org.springframework.boot.SpringApplication#run(java.lang.String...)
run方法创建并且刷新ApplicationContext。

public ConfigurableApplicationContext run(String... args) {
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		DefaultBootstrapContext bootstrapContext = createBootstrapContext();
		ConfigurableApplicationContext context = null;
		configureHeadlessProperty();
		
		//通过SpringFactoriesLoader在META-INF/spring.factories(key=org.springframework.boot.SpringApplicationRunListener)查询并且实例化SpringApplicationRunListener
		//SpringApplicationRunListener接口Spring有默认的实现EventPublishingRunListener,EventPublishingRunListener有SimpleApplicationEventMulticaster实例字段,用于分发处理事件。
		SpringApplicationRunListeners listeners = getRunListeners(args);
		
		//SpringApplicationRunListener启动操作,会发送ApplicationStartingEvent事件
		listeners.starting(bootstrapContext, this.mainApplicationClass);
		try {
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);

			//准备配置文件,包括创建和准备环境
			//根据WebApplicationType值在 SpringApplication#getOrCreateEnvironment 方法创建ConfigurableEnvironment实例
			//web应用使用WebApplicationType.SERVLET,对应ApplicationServletEnvironment
			
			//ConfigurableEnvironment准备:
			//1.ConfigurableEnvironment包含propertySources(属性源,例如application.yml),propertyResolver(数据类型转换)
			//2.listeners遍历所有的listener执行environmentPrepared方法。EventPublishingRunListener发送了ApplicationEnvironmentPreparedEvent事件。
			//EnvironmentPostProcessorApplicationListener监听ApplicationEnvironmentPreparedEvent事件,由EnvironmentPostProcessor.postProcessEnvironment()方法处理
			//EnvironmentPostProcessor添加新的配置文件(例如ConfigDataEnvironmentPostProcessor添加application.yml)
			ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);
			
			//System.Properties中配置spring.beaninfo.ignore,默认true
			configureIgnoreBeanInfo(environment);

			//打印banner
			Banner printedBanner = printBanner(environment);
			
			//创建ApplicationContext实例
			//由ApplicationContextFactory工厂根据WebApplicationType类型创建ApplicationContext
			//WebApplicationType:NO、SERVLET、REACTIVE
			//web应用使用WebApplicationType.SERVLET,对应AnnotationConfigServletWebServerApplicationContext
			context = createApplicationContext();
			context.setApplicationStartup(this.applicationStartup);

			//准备ApplicationContext
			//1.SpringApplication#postProcessApplicationContext,ApplicationContext后置处理。
			//1.1 如果SpringApplication包含BeanNameGenerator实例,BeanFactory注册BeanNameGenerator实例(bean名称生成者)。
			//1.2 如果SpringApplication包含ResourceLoader实例,ApplicationContext设置ResourceLoader实例。
			//1.3 为BeanFactory设置ConversionService,ConversionService实例与ConfigurableEnvironment.propertyResolver.conversionService一样。
			//2.SpringApplication#applyInitializers,为所有的ApplicationContextInitializer实例调用initialize方法。
			//添加Bean、BeanFactoryPostProcessor等准备和Bean定义等操作
			//3.SpringApplicationRunListeners#contextPrepared 上下文准备:
			//EventPublishingRunListener发送ApplicationContextInitializedEvent事件。
			//4.DefaultBootstrapContext#close 方法
			//发送BootstrapContextClosedEvent事件
			//5.BeanFactory注册单例ApplicationArguments、Banner
			//6.SpringApplication#lazyInitialization Boolean配置如果为true(默认为false),BeanFactory添加LazyInitializationBeanFactoryPostProcessor
			//7.SpringApplication#load加载SpringApplication.run方法传入的class,生成BeanDefine,并且添加到BeanFactory。
			//由org.springframework.boot.BeanDefinitionLoader类处理
			//8.SpringApplicationRunListeners#contextLoaded ApplicationContext加载完成
			//EventPublishingRunListener发送ApplicationPreparedEvent事件
			prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);

			//1.SpringApplicationShutdownHook#registerApplicationContext 注册ApplicationContext关闭钩子
			//通过ApplicationContextClosedListener监听ContextClosedEvent事件实现,仅是记录ApplicationContext正在使用还是关闭。
			//2.SpringApplication#refresh 实际上调用 ConfigurableApplicationContext#refresh刷新上下文。
			//refresh见解看下文
			refreshContext(context);
			afterRefresh(context, applicationArguments);
			stopWatch.stop();
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
			}
			listeners.started(context);
			callRunners(context, applicationArguments);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, listeners);
			throw new IllegalStateException(ex);
		}

		try {
			listeners.running(context);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, null);
			throw new IllegalStateException(ex);
		}
		return context;
	}

ApplicationContext.refresh

  代码入口org.springframework.context.support.AbstractApplicationContext#refresh。

@Override
	public void refresh() throws BeansException, IllegalStateException {
		synchronized (this.startupShutdownMonitor) {
			StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");

			// 准备此上下文以进行刷新。
			//1.设置状态变量值
			//AtomicBoolean active 为true(指示此上下文当前是否处于活动状态)
			//AtomicBoolean closed 为false(指示此上下文当前是否已关闭状态)
			//2.org.springframework.web.context.support.GenericWebApplicationContext#initPropertySources 替换servlet属性源
			//servletContextInitParams,servletConfigInitParams
			//3.监听器、事件赋值
			//earlyApplicationListeners,applicationListeners,earlyApplicationEvents
			prepareRefresh();

			// 通知ApplicationContext的子类刷新内置的BeanFactory实例,并且获取BeanFactory实例。
			ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

			// 准备BeanFactory,为ApplicationContext中使用做准备。
			//1.BeanFactory设置classLoader(ApplicationContext中的classLoader)
			//2.BeanFactory设置BeanExpressionResolver,默认使用StandardBeanExpressionResolver类实例,可以通过spring.spel.ignore配置取消设置,默认为false
			//3.org.springframework.beans.factory.config.ConfigurableBeanFactory#addPropertyEditorRegistrar 添加属性编辑者注册者,默认使用ResourceEditorRegistrar类实例。
			//4.org.springframework.beans.factory.config.ConfigurableBeanFactory#addBeanPostProcessor 
			//4.1添加ApplicationContextAwareProcessor类实例(处理ApplicationContextAware,EnvironmentAware等接口回调);
			//4.2添加ApplicationListenerDetector类实例,用于探测ApplicationListener接口实例,如果ApplicationListener接口实例为单例模式,加入ApplicationContext的listeners中,ApplicationListener接口实例销毁时从ApplicationContext的listeners中移除。
			//5.org.springframework.beans.factory.config.ConfigurableListableBeanFactory#ignoreDependencyInterface 忽略自动关联的给定依赖项接口.
			//5.1EnvironmentAware,
			//5.2 EmbeddedValueResolverAware,
			//5.3 ResourceLoaderAware,
			//5.4 ApplicationEventPublisherAware,
			//5.5 MessageSourceAware,
			//5.6 ApplicationContextAware,
			//5.7 ApplicationStartupAware
			//6.org.springframework.beans.factory.config.ConfigurableListableBeanFactory#registerResolvableDependency
			//在BeanFactory未定义为bea使用相应的自动连线值注册特殊依赖项类型,在可以正常自动注入对应的bean。
			//6.1 BeanFactory.class, beanFactory(前面obtainFreshBeanFactory()方法获取的实例)
			//6.2 ResourceLoader.class, 当前ApplicationContext实例
			//6.3 ApplicationEventPublisher.class, 当前ApplicationContext实例
			//6.4 ApplicationContext.class, 当前ApplicationContext实例
			//7.org.springframework.beans.factory.config.SingletonBeanRegistry#registerSingleton 把bean实例以bean名称注册为singleton。
			//不会执行任何初始化回调(特别是,它不会调用InitializingBean的afterPropertiesSet方法)。给定实例也不会收到任何销毁回调(如DisposableBean的销毁方法)。
			//7.1 environment->ApplicationContext.getEnvironment() 环境配置
			//7.2 systemProperties->ApplicationContext.getEnvironment().getSystemProperties() 系统属性配置
			//7.3 systemEnvironment->ApplicationContext.getEnvironment().getSystemEnvironment() 系统配置
			//7.4 applicationStartup->ApplicationContext.getApplicationStartup() 系统配置
			prepareBeanFactory(beanFactory);

			try {
				// 允许在ApplicationContext子类中对BeanFactory进行后处理(post-processing)。
				//1.org.springframework.beans.factory.config.ConfigurableBeanFactory#addBeanPostProcessor 添加BeanPostProcessor
				//WebApplicationContextServletContextAwareProcessor ,处理ServletContextAware,ServletConfigAware接口回调
				//2. org.springframework.beans.factory.config.ConfigurableListableBeanFactory#ignoreDependencyInterface 忽略ServletContextAware接口依赖处理
				//3. web应用特殊处理 org.springframework.web.context.support.WebApplicationContextUtils#registerWebApplicationScopes(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, javax.servlet.ServletContext)
				//3.1 org.springframework.beans.factory.config.ConfigurableBeanFactory#registerScope 注册给定的作用域,由给定的作用域实现支持。
				//request->RequestScope类实例
				//session->SessionScope类实例
				//application->ServletContextScope类实例
				//3.2 org.springframework.beans.factory.config.ConfigurableListableBeanFactory#registerResolvableDependency 注册指定class的实例
				//ServletRequest.class, new RequestObjectFactory()
				//ServletResponse.class, new ResponseObjectFactory()
				//HttpSession.class, new SessionObjectFactory()
				//WebRequest.class, new WebRequestObjectFactory()
				postProcessBeanFactory(beanFactory);

				StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");
				// 调用在ApplicationContext中注册为 BeanFactoryPostProcessor类。
				//org.springframework.context.support.PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors(org.springframework.beans.factory.config.ConfigurableListableBeanFactory, java.util.List<org.springframework.beans.factory.config.BeanFactoryPostProcessor>)
				invokeBeanFactoryPostProcessors(beanFactory);

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

				// Initialize message source for this context.
				initMessageSource();

				// 初始化ApplicationContext的事件广播器
				//applicationEventMulticaster使用SimpleApplicationEventMulticaster类实例,并且注册到BeanFactory(beanName=applicationEventMulticaster)
				initApplicationEventMulticaster();

				// 初始化特定ApplicationContext子类中的其他特殊bean。
				//web应用中,会调用org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext#createWebServer 创建web服务器。
				onRefresh();

				//在BeanFactory中寻找ApplicationListener接口实现类,并且把他们加到ApplicationContext.applicationListeners中。
				registerListeners();

				// 实例化所有剩余的(非惰性初始化)单例。
				//Bean实例化入口
				//实例化@Service、@Bean、@Component等注解类
				//关键代码入口 org.springframework.beans.factory.config.ConfigurableListableBeanFactory#preInstantiateSingletons
				finishBeanFactoryInitialization(beanFactory);

				//1.获取或者创建LifecycleProcessor实例,并且调用实例的onRefresh()方法 
				//2.发布ContextRefreshedEvent事件
				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();
				contextRefresh.end();
			}
		}
	}

ServletWebServerApplicationContext.refresh

  ServletWebServerApplicationContext在现有refresh基础上,如果出现异常,关闭web服务器。

@Override
	public final void refresh() throws BeansException, IllegalStateException {
		try {
		//调用 org.springframework.ui.context.support.UiApplicationContextUtils#initThemeSource 方法实例化 themeSource
			super.refresh();
		}
		catch (RuntimeException ex) {
		//发生异常时,关闭webServer
			WebServer webServer = this.webServer;
			if (webServer != null) {
				webServer.stop();
			}
			throw ex;
		}
	}

ConfigurableListableBeanFactory.preInstantiateSingletons

  ConfigurableListableBeanFactory#preInstantiateSingletons
实例化所有非惰性init单例,代码入口:
org.springframework.beans.factory.config.ConfigurableListableBeanFactory#preInstantiateSingletons
   详细可以阅读“Spring核心技术-Bean实例化

总结:

1.准备并且创建Environment;

2.创建ApplicationContext实例;

3.准备ApplicationContext,完成ApplicationContext的属性赋值,包括设置BeanNameGenerator、ResourceLoader等实例,发送ApplicationContextInitializedEvent、BootstrapContextClosedEvent、ApplicationPreparedEvent时间;

4.刷新ApplicationContext,这个阶段执行refresh操作。refresh操作主要是BeanFactory属性赋值、添加BeanFactoryPostProcessor、添加BeanPostProcessor等,以及实例化bean。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冲上云霄的Jayden

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值