前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SpringBoot源码解析:创建SpringApplication对象实例

SpringBoot源码解析:创建SpringApplication对象实例

作者头像
Java学习录
发布2019-09-25 14:10:25
3950
发布2019-09-25 14:10:25
举报
文章被收录于专栏:Java学习录

上篇文章SpringBoot自动装配原理解析中,我们分析了SpringBoot的自动装配原理以及@SpringBootApplication注解的原理,本篇文章则继续基于上篇文章中的main方法来分析SpringApplication这个类

代码语言:javascript
复制
@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

点击run方法一路跟踪下来,发现首先做的是实例化SpringApplication对象实例

代码语言:javascript
复制
public static ConfigurableApplicationContext run(Class<?> primarySource,
			String... args) {
		return run(new Class<?>[] { primarySource }, args);
	}
	public static ConfigurableApplicationContext run(Class<?>[] primarySources,
			String[] args) {
		return new SpringApplication(primarySources).run(args);
	}
	public SpringApplication(Class<?>... primarySources) {
		this(null, 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 = deduceWebApplicationType();
		setInitializers((Collection) getSpringFactoriesInstances(
				ApplicationContextInitializer.class));
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
		this.mainApplicationClass = deduceMainApplicationClass();
	}
  1. 首先看一下deduceWebApplicationType方法
代码语言:javascript
复制
private WebApplicationType deduceWebApplicationType() {
        if (ClassUtils.isPresent("org.springframework.web.reactive.DispatcherHandler", (ClassLoader)null) && !ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", (ClassLoader)null)) {
            return WebApplicationType.REACTIVE;
        } 
        for (String className : "javax.servlet.Servlet", org.springframework.web.context.ConfigurableWebApplicationContext") {
			if (!ClassUtils.isPresent(className, null)) {
				return WebApplicationType.NONE;
			}
	}
          return WebApplicationType.SERVLET;
        }
    }

大抵意思就是根据当前项目中是否存在上方的几个类来推断出当前的web环境,这里因为SpringBoot默认使用的web框架是SpringMVC,所以最后返回结果为WebApplicationType.SERVLET

  1. 加载所有的ApplicationContextInitializerApplicationListener的实现类
代码语言:javascript
复制
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
       ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
       Set<String> names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
       List<T> instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
       AnnotationAwareOrderComparator.sort(instances);
       return instances;
   }

可以看到主要还是用的SpringFactoriesLoader这个类去加载这两个接口的实现类,加载到类以后使用反射的方式构造出这些类的实例,然后根据这些实现类上的Order注解的值进行排序

关于这些实现类的具体作用请关注后续的文章

  1. 最后一行的意义是找到入口方法main所在的类,赋值给全局变量mainApplicationClass
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-09-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Java学习录 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档