启动流程
启动的整体流程如下图(引用自网络)
图片来源
启动中主要分为两步:
- 1、实例化SpringApplication对象
- 1.1 配置source
- 1.2 从类路径中推断web应用类型
- 1.3 设置初始化执行器,加载实现了ApplicationContextInitializer接口的类
- 1.4 设置应用监听器,加载实现了ApplicationListener接口的类
- 1.5 通过反射获取启动类
- 2、调用SpringApplication的run方法
- 2.1 启动计时器
- 2.2 配置headless属性
- 2.3 获取运行监听器 EventPublishingRunListener,启动监听器监听
- 2.4 预备环境信息
- 2.5 配置忽略的bean信息
- 2.6 打印springboot图标
- 2.7 创建应用上下文
- 2.8 实例化异常报告器
- 2.9 预备上下文
- 2.10 刷新上下文,注册bean到IOC容器
- 2.11 刷新上下文后处理
- 2.12 停止计时器
- 2.13 通知监听器:上下文已初始化
- 2.14 执行实现了ApplicationRunner和CommandLineRunner接口的启动执行类
- 2.15 发布ApplicationReadyEvent事件,通知监听器:应用已启动
具体的启动流程如下:
@SpringBootApplication
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) {
// 新建SpringApplication
SpringApplication app = new SpringApplication(Application.class);
// 执行run方法
app.run(args);
}
}
@SpringBootApplication是@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan三个注解的组合,可以提供SpringBoot配置,自动装配,组件扫描
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(excludeFilters = { @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
@AliasFor(annotation = EnableAutoConfiguration.class)
Class<?>[] exclude() default {};
@AliasFor(annotation = EnableAutoConfiguration.class)
String[] excludeName() default {};
@AliasFor(annotation = ComponentScan.class, attribute = "basePackages")
String[] scanBasePackages() default {};
@AliasFor(annotation = ComponentScan.class, attribute = "basePackageClasses")
Class<?>[] scanBasePackageClasses() default {};
@AliasFor(annotation = Configuration.class)
boolean proxyBeanMethods() default true;
}
new SpringApplication(Application.class)
的实现中会创建一个SpringApplication实例,应用上下文会装在来自于特定基础来源的beans
@SuppressWarnings({ "unchecked", "rawtypes" })
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
// 基础源
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
// 从类路径中推断web应用类型
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 设置初始化执行器,加载实现了ApplicationContextInitializer接口的类
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
// 设置应用监听器,加载实现了ApplicationListener接口的类
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
// 通过反射获取启动类
this.mainApplicationClass = deduceMainApplicationClass();
}
getSpringFactoriesInstances
方法可以获取spring 工厂实例
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
// 获取类加载器
ClassLoader classLoader = getClassLoader();
// 将加载的factory名字去重放入set中
Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
// 创建spring factory实例
List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
// 排序
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
getClassLoader
会调用ClassUtils#getDefaultClassLoader来获取默认的类加载器,该加载器先获取当前线程的类加载器,如果没有获取到,再获取当前类的类加载器,如果还是没有获取到,再获取系统的类加载器
public static ClassLoader getDefaultClassLoader() {
ClassLoader cl = null;
try {
// 当前线程的类加载器
cl = Thread.currentThread().getContextClassLoader();
} catch (Throwable ex) {
// Cannot access thread context ClassLoader - falling back...
}
if (cl == null) {
// 没有线程类加载器-》使用当前类的类加载器
cl = ClassUtils.class.getClassLoader();
if (cl == null) {
// getClassLoader() 返回null,表示bootstrap类加载器
try {
// 系统的类加载器
cl = ClassLoader.getSystemClassLoader();
}
catch (Throwable ex) {
// Cannot access system ClassLoader - oh well, maybe the caller can live with null...
}
}
}
return cl;
}
SpringFactoriesLoader.loadFactoryNames(type, classLoader)
会加载jar包的spring.factories中的配置类
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
// 根据classLoader从缓存中获取已加载的配置类
MultiValueMap<String, String> result = cache.get(classLoader);
if (result != null) {
return result;
}
try {
// FACTORIES_RESOURCE_LOCATION="META-INF/spring.factories",获取项目中所有引用的jar包的spring.factories文件位置URL
Enumeration<URL> urls = (classLoader != null ?
classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
result = new LinkedMultiValueMap<>();
while (urls.hasMoreElements()) {
// 加载具体的jar的spring.factories,如: jar:file:/D:/repository/org/springframework/spring-beans/5.2.5.RELEASE/spring-beans-5.2.5.RELEASE.jar!/META-INF/spring.factories
URL url = urls.nextElement();
UrlResource resource = new UrlResource(url);
// 加载spring.factories文件中具体的配置项,文件内容是kv形式的
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
for (Map.Entry<?, ?> entry : properties.entrySet()) {
// 获取key
String factoryTypeName = ((String) entry.getKey()).trim();
for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
// 获取value,存入result
result.add(factoryTypeName, factoryImplementationName.trim());
}
}
}
// 放入缓存
cache.put(classLoader, result);
return result;
} catch (IOException ex) {
throw new IllegalArgumentException("Unable to load factories from location [" +FACTORIES_RESOURCE_LOCATION + "]", ex);
}
}
createSpringFactoriesInstances
根据new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader))
获取的类名,通过反射的方式实例化类
private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes,
ClassLoader classLoader, Object[] args, Set<String> names) {
List<T> instances = new ArrayList<>(names.size());
for (String name : names) {
try {
// 反射获取类实例
Class<?> instanceClass = ClassUtils.forName(name, classLoader);
Assert.isAssignable(type, instanceClass);
// 获取该类声明的构造器
Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);
// 使用声明的构造器和参数实例化类
T instance = (T) BeanUtils.instantiateClass(constructor, args);
instances.add(instance);
} catch (Throwable ex) {
throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, ex);
}
}
return instances;
}
以上是new SpringApplication(Application.class)
的创建过程,接着是调用该对象的run方法
public ConfigurableApplicationContext run(String... args) {
StopWatch stopWatch = new StopWatch();
// 启动计时器
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
// 获取运行监听器 EventPublishingRunListener
SpringApplicationRunListeners listeners = getRunListeners(args);
// 启动监听器监听
listeners.starting();
try {
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
// 预备环境信息
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
// 配置忽略的bean信息
configureIgnoreBeanInfo(environment);
// 打印springboot图标
Banner printedBanner = printBanner(environment);
// 创建引用上下文
context = createApplicationContext();
// 实例化异常报告器
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
// 预备上下文
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
// 刷新上下文,注册bean到IOC容器
refreshContext(context);
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
// 通知监听器:上下文已初始化
listeners.started(context);
// 执行实现了ApplicationRunner和CommandLineRunner接口的启动执行类
callRunners(context, applicationArguments);
} catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
// 发布ApplicationReadyEvent事件,通知监听器:应用已启动
listeners.running(context);
}catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}
listeners.starting()
启动监听器会调用SpringApplicationRunListener#starting方法,这里的listener主要是EventPublishingRunListener
void starting() {
for (SpringApplicationRunListener listener : this.listeners) {
listener.starting();
}
}
EventPublishingRunListener#starting会调用广播事件方法multicastEvent,
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
// 事件类型
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
// 任务执行器
Executor executor = getTaskExecutor();
// getApplicationListeners(event, type)获取该类型事件的所有监听器
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
if (executor != null) { // 使用执行器调用监听器
executor.execute(() -> invokeListener(listener, event));
}
else { // 不使用执行器调用监听器
invokeListener(listener, event);
}
}
}
invokeListener(listener, event)
跟着会调用SimpleApplicationEventMulticaster#doInvokeListener
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
// 监听器监听到事件执行业务逻辑
listener.onApplicationEvent(event);
} catch (ClassCastException ex) {
String msg = ex.getMessage();
if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
// Possibly a lambda-defined listener which we could not resolve the generic event type for
// -> let's suppress the exception and just log a debug message.
Log logger = LogFactory.getLog(getClass());
if (logger.isTraceEnabled()) {
logger.trace("Non-matching event type for listener: " + listener, ex);
}
}
else {
throw ex;
}
}
}
prepareEnvironment(listeners, applicationArguments)
准备环境信息
private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments) {
// 创建和配置环境
ConfigurableEnvironment environment = getOrCreateEnvironment();
// 配置环境信息,配置文件相关信息加载
configureEnvironment(environment, applicationArguments.getSourceArgs());
// 绑定环境信息到配置属性源
ConfigurationPropertySources.attach(environment);
// 通知监听器:环境信息已加载
listeners.environmentPrepared(environment);
// 绑定到SpringApplication
bindToSpringApplication(environment);
// 定制化环境信息
if (!this.isCustomEnvironment) {
environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
deduceEnvironmentClass());
}
// 再次绑定环境信息到配置属性源
ConfigurationPropertySources.attach(environment);
return environment;
}
createApplicationContext()
创建应用上下文,根据不同的web应用类型,通过反射获取合适类型的上下文进行实例化
protected ConfigurableApplicationContext createApplicationContext() {
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
switch (this.webApplicationType) {
case SERVLET:
// 反射获取类对象
contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
break;
case REACTIVE:
contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
break;
default:
contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
}
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Unable create a default ApplicationContext, please specify an ApplicationContextClass", ex);
}
}
// 根据类的基本构造方法或默认构造方法实例化一个对象
return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}
prepareContext
private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
context.setEnvironment(environment);
// 应用上下文后处理
postProcessApplicationContext(context);
// 应用初始化器
applyInitializers(context);
// 通知监听器上下文已经准备好
listeners.contextPrepared(context);
// 打印启动信息
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
// 添加具体的单例bean
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
// 注册springApplicationArguments单例bean
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
if (beanFactory instanceof DefaultListableBeanFactory) {
// 设置允许bean定义覆盖
((DefaultListableBeanFactory) beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
if (this.lazyInitialization) { // 设置懒加载
context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
}
// 加载源sources
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
// 加载启动类的bean到IOC容器
load(context, sources.toArray(new Object[0]));
// 通知监听器上下文已加载
listeners.contextLoaded(context);
}
load(context, sources.toArray(new Object[0]))
加载bean到IOC容器的具体流程如下
protected void load(ApplicationContext context, Object[] sources) {
if (logger.isDebugEnabled()) {
logger.debug("Loading source " + StringUtils.arrayToCommaDelimitedString(sources));
}
// 创建bean加载器
BeanDefinitionLoader loader = createBeanDefinitionLoader(getBeanDefinitionRegistry(context), sources);
if (this.beanNameGenerator != null) {
loader.setBeanNameGenerator(this.beanNameGenerator);
}
if (this.resourceLoader != null) {
loader.setResourceLoader(this.resourceLoader);
}
if (this.environment != null) {
loader.setEnvironment(this.environment);
}
// 使用bean加载器加载bean
loader.load();
}
BeanDefinitionLoader#load()会先加载组件bean
private int load(Class<?> source) {
if (isGroovyPresent() && GroovyBeanDefinitionSource.class.isAssignableFrom(source)) {
// Any GroovyLoaders added in beans{} DSL can contribute beans here
GroovyBeanDefinitionSource loader = BeanUtils.instantiateClass(source, GroovyBeanDefinitionSource.class);
load(loader);
}
// 组件bean加载
if (isComponent(source)) {
// 注册source
this.annotatedReader.register(source);
return 1;
}
return 0;
}
AnnotatedGenericBeanDefinition#register 进行实际的bean注册
public void register(Class<?>... componentClasses) {
for (Class<?> componentClass : componentClasses) {
registerBean(componentClass);
}
}
public void registerBean(Class<?> beanClass) {
doRegisterBean(beanClass, null, null, null, null);
}
重头戏:doRegisterBean 完成实际的bean注册。
private <T> void doRegisterBean(Class<T> beanClass, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, @Nullable Supplier<T> supplier,
@Nullable BeanDefinitionCustomizer[] customizers) {
// 为给定的bean class创建一个AnnotatedGenericBeanDefinition
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
// 基于@Conditional注解判断一个bean是否要跳过
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
abd.setInstanceSupplier(supplier);
// 解析范围元数据
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
// 获取beanName, 默认是类名的首字母小写
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
// 处理通用定义注解
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
if (qualifiers != null) {
for (Class<? extends Annotation> qualifier : qualifiers) {
if (Primary.class == qualifier) {
abd.setPrimary(true);
}
else if (Lazy.class == qualifier) {
abd.setLazyInit(true);
}
else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
if (customizers != null) {
for (BeanDefinitionCustomizer customizer : customizers) {
customizer.customize(abd);
}
}
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
// 范围代理模式处理,一般是NO
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
// 注册bean
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
BeanDefinitionReaderUtils.registerBeanDefinition
会将bean注册到上下文的bean factory里面
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// Register bean definition under primary name.
String beanName = definitionHolder.getBeanName();
// 注册bean定义
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// 注册bean别名,如果有
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
registry.registerAlias(beanName, alias);
}
}
}
listeners.contextLoaded(context)
会调用到EventPublishingRunListener#contextLoaded方法
public void contextLoaded(ConfigurableApplicationContext context) {
for (ApplicationListener<?> listener : this.application.getListeners()) {
// 如果监听器实现了ApplicationContextAware接口,就会执行上下文初始化
if (listener instanceof ApplicationContextAware) {
((ApplicationContextAware) listener).setApplicationContext(context);
}
// 上下文中添加监听器
context.addApplicationListener(listener);
}
// 广播应用已经准备好事件
this.initialMulticaster.multicastEvent(new ApplicationPreparedEvent(this.application, this.args, context));
}
run#refreshContext会刷新上下文
private void refreshContext(ConfigurableApplicationContext context) {
refresh(context);
if (this.registerShutdownHook) {
try {
context.registerShutdownHook();
}
catch (AccessControlException ex) {
// Not allowed in some environments.
}
}
}
该方法会调用AbstractApplicationContext#refresh
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
// 为刷新准备上下文
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
// 告诉子类去刷新内部的bean factory
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
// 在此上下文中准备bean factory
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
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();
}
}
}