SpringApplication Classes that can be used to bootstrap and launch a Spring application from a Java main method
在java的main方法中使用该类用于引导和启动一个spring应用程序
By default class will perform(执行) the following steps to bootstrap your application
- Create an appropriate(适当的) {ApplicationContext} instance(实例) (depending on your classpath)
- Register(注册) a {CommandLinePropertySource} to expose (暴露) command line arguments as Spring properties
- Refresh(刷新) the application context, loading(加载) all singleton beans
- Trigger(触发) any {CommandLineRunner} beans
创建 ApplicationContext
注册 CommandLinePropertySource
刷新 应用程序上下文环境,加载 all singleton beans
触发 CommandLineRunner beans
new SpringApplication(sources).run(args)
1. new SpringApplication(sources)
1.1 initialize(sources)
2. run(args)
private final Set<Object> sources = new LinkedHashSet<Object>()
private void initialize(Object[] sources) {
if (sources != null && sources.length > 0) {
this.sources.addAll(Arrays.asList(sources)); // 1 name = com.xst.springboot01.SpringBoot01Application
}
this.webEnvironment = deduceWebEnvironment(); // 2 true
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));// 3
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); // 4
this.mainApplicationClass = deduceMainApplicationClass(); // 5
}
//1
private final Set<Object> sources = new LinkedHashSet<Object>();
// 2
private boolean webEnvironment;
//3
private List<ApplicationContextInitializer<?>> initializers; // size:7
// 4
private List<ApplicationListener<?>> listeners; //size:11
// 5
private Class<?> mainApplicationClass;
// mainApplicationClass:com.xst.springboot01.SpringBoot01Application
private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type,
Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
// Use names and ensure unique to protect against duplicates
Set<String> names = new LinkedHashSet<String>(
SpringFactoriesLoader.loadFactoryNames(type, classLoader));
List<T> instances = createSpringFactoriesInstances(type, parameterTypes,
classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
private <T> List<T> createSpringFactoriesInstances(Class<T> type,
Class<?>[] parameterTypes, ClassLoader classLoader, Object[] args,
Set<String> names) {
List<T> instances = new ArrayList<T>(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;
}
public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
String factoryClassName = factoryClass.getName();
try {
Enumeration<URL> urls = (classLoader != null ? classLoader.getResources(FACTORIES_RESOURCE_LOCATION) :
ClassLoader.getSystemResources(FACTORIES_RESOURCE_LOCATION));
List<String> result = new ArrayList<String>();
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
String factoryClassNames = properties.getProperty(factoryClassName);
result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));
}
return result;
}
catch (IOException ex) {
throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() +
"] factories from location [" + FACTORIES_RESOURCE_LOCATION + "]", ex);
}
}