Springboot源码深度解析,方法解析,类加载解析,容器建立
Posted dsj1188
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Springboot源码深度解析,方法解析,类加载解析,容器建立相关的知识,希望对你有一定的参考价值。
springboot的启动都是从main方法开始的,如下:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
后面会进入SpringApplication的初始化方法:
public static ConfigurableApplicationContext run(Object[] sources, String[] args) {
return new SpringApplication(sources).run(args);
}
public SpringApplication(Object... sources) {
initialize(sources);
}
我们进入initialize(Object[] sources)查看逻辑:
private void initialize(Object[] sources) {
if (sources != null && sources.length > 0) {
this.sources.addAll(Arrays.asList(sources));
}
this.webEnvironment = deduceWebEnvironment();
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInitializer.class));
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
this.mainApplicationClass = deduceMainApplicationClass();
}
deduceWebEnvironment()方法是验证是否有web运行的环境,方法就是查看下tomcat以及spring中的某个类是否存在,以此来验证是否有web环境运行条件,代码如下:
private boolean deduceWebEnvironment() {
for (String className : WEB_ENVIRONMENT_CLASSES) {
if (!ClassUtils.isPresent(className, null)) {
return false;
}
}
return true;
}
initialize()方法中的第二个方法就是
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInitializer.class));
这个方法后面会进入getSpringFactoriesInstances方法,其内容如下:
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;
}
上面方法中:
第一个方法获取了当前加载类的classLoader,即加载第三方类库的AppClassLoader。
第二个方法是加载了所有jar包以及classes下面的所有“META-INF/spring.factories”文件,并将其key为“org.springframework.context.ApplicationContextInitializer”的所有value放入了一个集合中,为了避免重复,放入了一个Set集合中将数据返回。其包含的类型有如下几种,即names的Set集合中的值有如下几种:
0 = "org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer"
1 = "org.springframework.boot.context.ContextIdApplicationContextInitializer"
2 = "org.springframework.boot.context.config.DelegatingApplicationContextInitializer"
3 = "org.springframework.boot.context.embedded.ServerPortInfoApplicationContextInitializer"
4 = "org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer"
5 = "org.springframework.boot.autoconfigure.logging.AutoConfigurationReportLoggingInitializer"
3.第三个方法createSpringFactoriesInstances是创建了上述类型的实例,
4.第四个方法AnnotationAwareOrderComparator.sort(instances);会根据AnnotationAwareOrderComparator的排序规则进行排序执行,将instances进行排序。
最后在外面将这些排序好的initializers设置到了SpringApplication的initializers的属性之中。
在springApplication的initialize方法的后面一个方法setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));中是设置org.springframework.context.ApplicationListener类的实例到类SpringApplication的listeners属性当中。
springApplication的initialize方法中的最后一个方法this.mainApplicationClass = deduceMainApplicationClass();是获取启动类,其方法如下:
private Class<?> deduceMainApplicationClass() {
try {
StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
for (StackTraceElement stackTraceElement : stackTrace) {
if ("main".equals(stackTraceElement.getMethodName())) {
return Class.forName(stackTraceElement.getClassName());
}
}
}
catch (ClassNotFoundException ex) {
// Swallow and continue
}
return null;
}
是通过RuntimeException寻找栈轨迹打印的方法中获取main方法的类,以此来获得启动类。
至此,关于initialize方法的所有过程就说完了。下面我们就要进入run方法的过程说明了。
---------------------
作者:lz710117239
来源:CSDN
原文:https://blog.csdn.net/lz710117239/article/details/80068588
版权声明:本文为博主原创文章,转载请附上博文链接!
以上是关于Springboot源码深度解析,方法解析,类加载解析,容器建立的主要内容,如果未能解决你的问题,请参考以下文章