SpringBoot源码解读-1启动

启动

@SpringBootApplication	  //springboot的核心注解
public class App {

    public static void main(String[] args) {
        SpringApplication.run(App.class, args);
        //run(args);
    }

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

@SuppressWarnings({ "unchecked", "rawtypes" })
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
	this.resourceLoader = resourceLoader;
    Assert.notNull(primarySources, "PrimarySources must not be null");
    this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
//见2.1推断当前环境为哪种环境WebApplicationType 
    this.webApplicationType = WebApplicationType.deduceFromClasspath();
//见2.2初始化initializers,即设置应用上下文初始化器
    setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
//见2.3初始化listeners,即设置监听器
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
//见2.4推断应用的入口类
    this.mainApplicationClass = deduceMainApplicationClass();
}

2.1推断当前环境为哪种环境WebApplicationType

static WebApplicationType deduceFromClasspath() {
   if (ClassUtils.isPresent("org.springframework.web.reactive.DispatcherHandler", null) && !ClassUtils.isPresent("org.springframework.web.servlet.DispatcherServlet", null)
         && !ClassUtils.isPresent("org.glassfish.jersey.servlet.ServletContainer", null)) {
      return WebApplicationType.REACTIVE;
   }
final String[] SERVLET_INDICATOR_CLASSES = { "javax.servlet.Servlet",
      "org.springframework.web.context.ConfigurableWebApplicationContext" };
   for (String className : SERVLET_INDICATOR_CLASSES) {
      if (!ClassUtils.isPresent(className, null)) {
         return WebApplicationType.NONE;
      }
   }
   return WebApplicationType.SERVLET;
}

代码逻辑:

  1. 如果满足该条件(加载字节码文件DispatcherHandler成功 && DispatcherServlet失败 && ServletContainer失败)则设置app类型为REACTIVE;
  2. 如果满足该条件(加载字节码文件Servlet失败 || ConfigurableWebApplicationContext失败)则设置app类型为NONE;
  3. 其他为SERVLET。

(其实加载字节码文件就是有没有引入这个类,idea中按shift+shift搜索一下就可以)

返回值为WebApplicationType枚举类型,有三种

  1. NONE
  2. SERVLET
  3. REACTIVE 请求响应式

2.2

private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) {
    return this.getSpringFactoriesInstances(type, new Class[0]);
}

private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
    ClassLoader classLoader = this.resourceLoader != null ? this.resourceLoader.getClassLoader() : ClassUtils.getDefaultClassLoader();
//见2.2.1
//返回值为所有META-INF/spring.factories文件中key=org.springframework.context.ApplicationContextInitializer的value:
//org.springframework.boot.context.			ConfigurationWarningsApplicationContextInitializer
//org.springframework.boot.context.			ContextIdApplicationContextInitializer
//org.springframework.boot.context.config.		DelegatingApplicationContextInitializer
//org.springframework.boot.rsocket.context.		RSocketPortInfoApplicationContextInitializer
//org.springframework.boot.web.context.			ServerPortInfoApplicationContextInitializer
//org.springframework.boot.autoconfigure.			SharedMetadataReaderFactoryContextInitializer
//org.springframework.boot.autoconfigure.logging.		ConditionEvaluationReportLoggingListener
    Set<String> names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
    List<T> instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
    //排序,重写了compareTo方法,回调getOrder()方法得到一个整形数字,就是决定顺序
    AnnotationAwareOrderComparator.sort(instances);
    return instances;
}

@SuppressWarnings("unchecked")
private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes,
		ClassLoader classLoader, Object[] args, Set<String> names) {
	List<T> instances = new ArrayList<>(names.size());
	for (String name : names) {
		try {
            //加载字节码文件
			Class<?> instanceClass = ClassUtils.forName(name, classLoader);
			Assert.isAssignable(type, instanceClass);
            //通过反射获取构造器
			Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);
            //通过构造器new实例对象
			T instance = (T) BeanUtils.instantiateClass(constructor, args);
			instances.add(instance);
		}catch (Throwable ex) {
			throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, ex);
		}
	}
	return instances;
}

返回值有7个实例对象:为所有META-INF/spring.factories文件中key=org.springframework.context.ApplicationContextInitializer的value:

  1. org.springframework.boot.context.config.DelegatingApplicationContextInitializer
  2. org.springframework.boot.autoconfigure.SharedMetadataReaderFactoryContextInitializer
  3. org.springframework.boot.context.ContextIdApplicationContextInitializer
  4. org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer
  5. org.springframework.boot.rsocket.context.RSocketPortInfoApplicationContextInitializer
  6. org.springframework.boot.web.context.ServerPortInfoApplicationContextInitializer
  7. org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener

2.2.1加载META/INF/spring.factories文件中的所有属性并缓存如cache,key为factories文件中的key,value为值数组

public static List<String> loadFactoryNames(Class<?> factoryType, @Nullable ClassLoader classLoader) {
	String factoryTypeName = factoryType.getName();
	return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());
}

private static Map<String, List<String>> loadSpringFactories(@Nullable ClassLoader classLoader) {
	MultiValueMap<String, String> result = cache.get(classLoader);
	if (result != null) {
		return result;
	}
	try {
	Enumeration<URL> urls = (classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories"));
	result = new LinkedMultiValueMap<>();
	while (urls.hasMoreElements()) {
		URL url = urls.nextElement();
		UrlResource resource = new UrlResource(url);
		Properties properties = PropertiesLoaderUtils.loadProperties(resource);
		for (Map.Entry<?, ?> entry : properties.entrySet()) {
			String factoryTypeName = ((String) entry.getKey()).trim();
			for (String factoryImplementationName : StringUtils.commaDelimitedListToStringArray((String) entry.getValue())) {
				result.add(factoryTypeName, factoryImplementationName.trim());
			}
		}
	}
	cache.put(classLoader, result);
	return result;
}catch (IOException ex) {
	throw new IllegalArgumentException("Unable to load factories from location [" +
			"META-INF/spring.factories"+ "]", ex);
}
}

2.3获取方式同2.2,此时key=org.springframework.context.ApplicationListener,有10种

  1. org.springframework.boot.context.config.ConfigFileApplicationListener
  2. org.springframework.boot.context.config.AnsiOutputApplicationListener
  3. org.springframework.boot.context.logging.LoggingApplicationListener
  4. org.springframework.boot.context.logging.ClasspathLoggingApplicationListener
  5. org.springframework.boot.autoconfigure.BackgroundPreinitializer
  6. org.springframework.boot.context.config.DelegatingApplicationListener
  7. org.springframework.boot.builder.ParentContextCloserApplicationListener
  8.          org.springframework.boot.ClearCachesApplicationListener
  9.          org.springframework.boot.context.FileEncodingApplicationListener
  10.          org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener

在通过反射调用上述10个类的无参构造器new实例时,都没有额外的初始化工作。

2.4推断应用的入口类


private Class<?> deduceMainApplicationClass() {
    try {
	//StackTrace(堆栈轨迹)存放的就是方法调用栈的信息
	//获取StackTraceElement的方法有两种,均返回StackTraceElement数组,也就是这个栈的信息。
	//1、Thread.currentThread().getStackTrace()
	//2、new Throwable().getStackTrace()
	//StackTraceElement数组包含了StackTrace(堆栈轨迹)的内容,通过遍历它可以得到方法间的调用过程,即可以得到当前方法以及其调用	//者的方法名、调用行数等信息
        StackTraceElement[] stackTrace = (new RuntimeException()).getStackTrace();
        StackTraceElement[] var2 = stackTrace;
        int var3 = stackTrace.length;

        for(int var4 = 0; var4 < var3; ++var4) {
            StackTraceElement stackTraceElement = var2[var4];
            if ("main".equals(stackTraceElement.getMethodName())) {
                return Class.forName(stackTraceElement.getClassName());
            }
        }
    } catch (ClassNotFoundException var6) {
    }
    return null;
}

猜你喜欢

转载自blog.csdn.net/qq_33436466/article/details/103170932