1. 程式人生 > 其它 >SpringBoot原始碼解析建立SpringApplication物件例項

SpringBoot原始碼解析建立SpringApplication物件例項

上篇文章中的main方法來分析SpringApplication這個類

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

點選run方法一路跟蹤下來,發現首先做的是例項化SpringApplication物件例項

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方法
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的實現類
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