主要对spring boot的源代码进行解析,解析的内容包括启动顺序、代码的作用和设计代码的设计模式。第一次内容目标需要解决的问题关于springboot的配置的加载!
Spring Boot的入口类
1 2 3 4 5 6 7 8
| @SpringBootApplication public class SpringBootBestPracticeApplication {
public static void main(String[] args) { SpringApplication.run(SpringBootBestPracticeApplication.class, args); } }
|
以上入口类主要使用SpringApplication
中的方法,跟踪代码进入run
1 2 3 4 5 6 7 8 9 10 11 12
| 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); }
|
函数上的注释为函数的英文注释的中文翻译。
其中第一个参数primarySource
:加载主要资源类(未知用途)
第二个参数args
:用于传递参数(未知用途)
设计模式:采用了静态工厂方法,其中主要让创建对象的时候返回其它类型的对象且具有可读性。—<>
SpringApplication
实例化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| 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(); }
|
SpringApplication
实例化过程中经过了7
个步骤,前3
个步骤集中于对resourceLoader
、primarySources
的初始与判定,较为简单。后四个步骤为实例化的重点
推断web
类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| private WebApplicationType deduceWebApplicationType() { if (ClassUtils.isPresent(REACTIVE_WEB_ENVIRONMENT_CLASS, null) && !ClassUtils.isPresent(MVC_WEB_ENVIRONMENT_CLASS, null) && !ClassUtils.isPresent(JERSEY_WEB_ENVIRONMENT_CLASS, null)) { return WebApplicationType.REACTIVE; } for (String className : WEB_ENVIRONMENT_CLASSES) { if (!ClassUtils.isPresent(className, null)) { return WebApplicationType.NONE; } } return WebApplicationType.SERVLET; }
public enum WebApplicationType {
NONE,
SERVLET,
REACTIVE
}
|
ClassUtils.isPresent
函数主要用于确定类是否存在
WebApplicationType
有三种类型,None
表示不是以一个web应用启动,servlet
表示以servlet
为基础的web应用,REACTIVE
表示是一个reactive的web。REACTIVE
本人研究不多,按照Spring
官方说法是一个非阻塞的web框架,其使用到的maven为spring-boot-starter-webflux
设置应用上下文初始化器
1 2
| setInitializers((Collection) getSpringFactoriesInstances( ApplicationContextInitializer.class));
|
应用上下文初始化器的作用
1 2 3 4 5 6 7 8 9
| public interface ApplicationContextInitializer<C extends ConfigurableApplicationContext> {
void initialize(C applicationContext);
}
|
用来初始化指定的 Spring 应用上下文,如注册属性资源、激活配置文件等
设置应用上下文初始化
1 2 3 4 5
| public void setInitializers( Collection<? extends ApplicationContextInitializer<?>> initializers) { this.initializers = new ArrayList<>(); this.initializers.addAll(initializers); }
|
只是将其初始化一个名为initializers
的集合
getSpringFactoriesInstances
的作用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| private <T> Collection<T> getSpringFactoriesInstances(Class<T> type) { return getSpringFactoriesInstances(type, new Class<?>[] {}); }
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 = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names); AnnotationAwareOrderComparator.sort(instances); return instances; }
|