启动类如下,在启动类中调用 org.springframework.boot.SpringApplication 类的静态run方法
@SpringBootApplication
public class SpringbootDemoApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootDemoApplication.class, args);
}
}
如下是 SpringApplication 静态 run方法 有多个重载方法,在run方法中创建了一个SpringApplication 实例,并调用实例的run方法,如下:
public static ConfigurableApplicationContext run(Class> primarySource, String... args) {
return run(new Class[]{primarySource}, args);
}
public static ConfigurableApplicationContext run(Class>[] primarySources, String[] args) {
return (new SpringApplication(primarySources)).run(args);
}
②SpringApplication 实例化
public SpringApplication(ResourceLoader resourceLoader, Class>... primarySources) {
this.sources = new linkedHashSet();
this.bannerMode = Mode.CONSOLE;
this.logStartupInfo = true;
this.addCommandLineProperties = true;
this.addConversionService = true;
this.headless = true;
this.registerShutdownHook = true;
this.additionalProfiles = Collections.emptySet();
this.isCustomEnvironment = false;
this.lazyInitialization = false;
this.applicationContextFactory = ApplicationContextFactory.DEFAULT;
this.applicationStartup = ApplicationStartup.DEFAULT;
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new linkedHashSet(Arrays.asList(primarySources));
//根据引入的依赖判断当前应用类型
this.webApplicationType = WebApplicationType.deduceFromClasspath();
//初始化RegistryInitializers(注册初始化器),getSpringFactoriesInstances方法在很多地方都用到需要重点关注
this.bootstrapRegistryInitializers = new ArrayList(this.getSpringFactoriesInstances(BootstrapRegistryInitializer.class));
this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
//初始化监听器
this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = this.deduceMainApplicationClass();
}
deduceFromClasspath 方法:
deduceFromClasspath 方法内部通过使用 Class.forName 加载类的方式判断对应的类型,不同类型与Class对象对应关系如下:
REACTIVE:存在 org.springframework.web.reactive.DispatcherHandler Class对象 NONE: (如果不存在右边其中一个类则为none) javax.servlet.Servlet, org.springframework.web.context.ConfigurableWebApplicationContext SERVLET: 不是以上两种类型则为 SERVLET
具体逻辑可以看 org.springframework.boot.WebApplicationType
getSpringFactoriesInstances 方法:
privateCollection getSpringFactoriesInstances(Class type, Class>[] parameterTypes, Object... args) { ClassLoader classLoader = this.getClassLoader(); //loadFactoryNames从配置文件中根据factoryTypeName加载类名称集合 Set names = new linkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader)); List instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names); AnnotationAwareOrderComparator.sort(instances); return instances; }
org.springframework.core.io.support.SpringFactoriesLoader.loadFactoryNames 方法:
根据类类型获取配置类的名称集合,例如: org.springframework.context.ApplicationContextInitializer 作为key获取:
# Application Context Initializers org.springframework.context.ApplicationContextInitializer= org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer, org.springframework.boot.context.ContextIdApplicationContextInitializer, org.springframework.boot.context.config.DelegatingApplicationContextInitializer, org.springframework.boot.rsocket.context.RSocketPortInfoApplicationContextInitializer, org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer
public static ListloadFactoryNames(Class> factoryType, @Nullable ClassLoader classLoader) { ClassLoader classLoaderToUse = classLoader; if (classLoader == null) { classLoaderToUse = SpringFactoriesLoader.class.getClassLoader(); } String factoryTypeName = factoryType.getName(); //核心方法为 loadSpringFactories return (List)loadSpringFactories(classLoaderToUse).getOrDefault(factoryTypeName, Collections.emptyList()); }
org.springframework.core.io.support.SpringFactoriesLoader.loadSpringFactories 方法:
private static Map> loadSpringFactories(ClassLoader classLoader) { Map > result = (Map)cache.get(classLoader); if (result != null) { return result; } else { HashMap result = new HashMap(); try { //读取配置 Enumeration urls = classLoader.getResources("meta-INF/spring.factories"); while(urls.hasMoreElements()) { URL url = (URL)urls.nextElement(); UrlResource resource = new UrlResource(url); Properties properties = PropertiesLoaderUtils.loadProperties(resource); Iterator var6 = properties.entrySet().iterator(); while(var6.hasNext()) { Entry, ?> entry = (Entry)var6.next(); String factoryTypeName = ((String)entry.getKey()).trim(); String[] factoryImplementationNames = StringUtils.commaDelimitedListToStringArray((String)entry.getValue()); String[] var10 = factoryImplementationNames; int var11 = factoryImplementationNames.length; for(int var12 = 0; var12 < var11; ++var12) { String factoryImplementationName = var10[var12]; ((List)result.computeIfAbsent(factoryTypeName, (key) -> { return new ArrayList(); })).add(factoryImplementationName.trim()); } } } result.replaceAll((factoryType, implementations) -> { return (List)implementations.stream().distinct().collect(Collectors.collectingAndThen(Collectors.toList(), Collections::unmodifiableList)); }); cache.put(classLoader, result); return result; } catch (IOException var14) { throw new IllegalArgumentException("Unable to load factories from location [meta-INF/spring.factories]", var14); } } }
meta-INF/spring.factories 配置有两处地方,如下:
SpringFactoriesLoader 类将工厂名对应的类名集合存放到cache中,static final Map
initializers ,listeners 初始化如下:



