Table of contents
SpringApplication::SpringApplication
I haven't watched SpringBoot for a long time, so I'll review it and learn from the past.
@SpringBootApplication
public class SecurityApplication {
public static void main(String[] args) {
SpringApplication.run(SecurityApplication.class,args);
}
}
annotation
- The declaration is a spring application configuration class
- Load this class into the ioc container to complete package scanning
- Import configuration class
- According to the defined scanning path, assemble the classes that meet the scanning rules into the spring container
SpringApplication::SpringApplication
Except for the annotation, there is only one line of code
SpringApplication.run(SecurityApplication.class,args);
Let's analyze the run method, click in and see
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return (new SpringApplication(primarySources)).run(args);
}
Let's analyze first
(new SpringApplication(primarySources))
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
// 壹
this.resourceLoader = resourceLoader;
Assert.notNull(primarySources, "PrimarySources must not be null");
// 贰
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
// 叁
this.webApplicationType = WebApplicationType.deduceFromClasspath();
// 肆
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
// 伍
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
// 陆
this.mainApplicationClass = deduceMainApplicationClass();
}
one
Configure resourceLoader
two
Configure the main startup class
three
Determine the type of the current application.
static WebApplicationType deduceFromClasspath() {
if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
&& !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
return WebApplicationType.REACTIVE;
}
for (String className : SERVLET_INDICATOR_CLASSES) {
if (!ClassUtils.isPresent(className, null)) {
return WebApplicationType.NONE;
}
}
return WebApplicationType.SERVLET;
}
Determine the application type (reflection) based on whether the Class exists .
four
Get the instance object of the initializer
(Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class)Click inside the code, go to
loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
Step 1: Let's look at loadSpringFactories(classLoader)
Mainly get the classes that need to be loaded from META-INF/spring.factories (deduplication), and finally put them in the cache
private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
MultiValueMap<String, String> result = cache.get(classLoader);
if (result != null) {
return result;
}
try {
Enumeration<URL> urls = (classLoader != null ?
classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
result = new LinkedMultiValueMap<>();
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
UrlResource resource = new UrlResource(url);
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
for (Map.Entry<?, ?> entry : properties.entrySet()) {
String factoryTypeName = ((String) entry.getKey()).trim();
for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
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);
}
}
In the second step, let's look at getOrDefault(factoryTypeName, Collections.emptyList()) :
Take the key out of the map as the value of ApplicationContextInitializer.
Wu
Get the instance object of the listener
The analysis process is the same as above
land
Find the main class of the current application and start executing