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。