码迷,mamicode.com
首页 > 编程语言 > 详细

Springboot源码深度解析,方法解析,类加载解析,容器建立

时间:2018-12-09 22:03:20      阅读:207      评论:0      收藏:0      [点我收藏+]

标签:boot   classname   ble   stat   tap   ida   dap   .config   原创文章   

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源码深度解析,方法解析,类加载解析,容器建立

标签:boot   classname   ble   stat   tap   ida   dap   .config   原创文章   

原文地址:https://www.cnblogs.com/dsj1188/p/10093459.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!