springBoot源码分析

当前所有项目都用到了springboot,至于刚接触springboot的同学,这边文章不予介绍,度娘有很多,自行去看。

这边文章主要针对启动springboot的源码分析。

分析springboot源码:

1.首先从我们自己的main方法中进入的源码是这个方法,从字面意思可以看出可以配置应用上下文,也就是环境,这个方法我理解真正进入run方法的一个工具方法,为了自定义类中main方法调用,source参数含义是自定义类的class,args是main方法中的参数

public static ConfigurableApplicationContext run(Object source, String... args) {

return run(new Object[] { source }, args);

}

2.这个方法是springApplication类构造方法执行和真正run方法执行

public static ConfigurableApplicationContext run(Object[] sources, String[] args) {

return new SpringApplication(sources).run(args);

}

2.1首先是构造方法的执行,首先从字面意思看这个方法初始化,具体初始化什么东西我们看里面的逻辑

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();

}

2.1.1 这个逻辑只是把我们自定义的类对象添加的全局set集合中,具体什么用法现在还没有看出来

if (sources != null && sources.length > 0) {

this.sources.addAll(Arrays.asList(sources));

}

2.1.2 首先从字面意思看这个方法是,推导出web 环境,判断当前是否是web环境

this.webEnvironment = deduceWebEnvironment();

private boolean deduceWebEnvironment() {

for (String className : WEB_ENVIRONMENT_CLASSES) {

if (!ClassUtils.isPresent(className, null)) {

return false;

}

}

return true;

}

2.1.3 然后在setInitializers((Collection) getSpringFactoriesInstances(

ApplicationContextInitializer.class)); 执行了获取spring工程实例的方法如下:

a.这个方法首先是获取当前线程上下文类对象

b.然后通过spring工厂加载器读取工厂名字SET通过传入集合ApplicationContextInitializer 和单签类加载器对象

c.然后再是创建spring工厂实例List集合

d.通过比较AnnotationAwareOrderComparator 对上面查询的工厂实例进行排序

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;

}

2.1.3.1 最后执行这个方法:从字面意思看是设置spring工厂集合实例,添加到全局initializers中去,

initializers这个作用是一个存储初始化后应该上下文子类 这个存储的是spring工厂实例集合

public void setInitializers(

Collection<? extends ApplicationContextInitializer<?>> initializers) {

this.initializers = new ArrayList<ApplicationContextInitializer<?>>();

this.initializers.addAll(initializers);

}

2.1.4 这个和上面分析是一样的 只是传入的参数不同,结果是获取监听实例然和存储到全局变量listeners中去

setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));

2.1.5 最后这个方面就是推到拿到我们自定义启动main方法的类存储到mainApplicationClass全局变量中

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;

}

以上就是springboot项目启动时,SpringApplication构造器初始化源码分析

结论:springboot在使用构造器进入初始化时:

第一:存储我们自定义启动类,把这个对象存放到全局变量sources集合中

第二:通过 源码中这个WEB_ENVIRONMENT_CLASSES这个全部静态变量数据推导出环境是不是web环境

第三:设置初始化器,通过initializers全局变量存储 ApplicationContextInitializer spring工厂中实例

第四:设置监听器,通过listeners全局变量存储ApplicationListener spring工厂实例

最后就是拿到我们自己定义启动springboot的类存在该类Class对象

 

 

 

持不同意见的同学可以评论,一起交流,一起进步。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值