SpringBoot启动流程源码解析,版本号为1.5.7
SpringApplication创建
1 | run方法调用 |
加载Initializers
1 | private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type) { |
以上关键代码为SpringFactoriesLoader.loadFactoryNames(type, classLoader) 源码如下,通过以下代码返回spring.factories中ApplicationContextInitializer配置的value返回需要创建对象的名称1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {
String factoryClassName = factoryClass.getName();
try {
Enumeration<URL> urls = classLoader != null ? classLoader.getResources("META-INF/spring.factories") : ClassLoader.getSystemResources("META-INF/spring.factories");
ArrayList result = new ArrayList();
while(urls.hasMoreElements()) {
URL url = (URL)urls.nextElement();
Properties properties = PropertiesLoaderUtils.loadProperties(new UrlResource(url));
String factoryClassNames = properties.getProperty(factoryClassName);
result.addAll(Arrays.asList(StringUtils.commaDelimitedListToStringArray(factoryClassNames)));
}
return result;
} catch (IOException var8) {
throw new IllegalArgumentException("Unable to load [" + factoryClass.getName() + "] factories from location [" + "META-INF/spring.factories" + "]", var8);
}
}
通过以上代码分析得知通过spring.factories文件加载所有Initializers,spring.factories文件如下所示1
2
3
4
5org.springframework.context.ApplicationContextInitializer=\
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\
org.springframework.boot.context.ContextIdApplicationContextInitializer,\
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\
org.springframework.boot.context.web.ServerPortInfoApplicationContextInitializer
通过类全称创建对象,对应上一步会生成ConfigurationWarningsApplicationContextInitializer,ContextIdApplicationContextInitializer,DelegatingApplicationContextInitializer,ServerPortInfoApplicationContextInitializer四个对象1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, ClassLoader classLoader, Object[] args, Set<String> names) {
List<T> instances = new ArrayList(names.size());
Iterator var7 = names.iterator();
while(var7.hasNext()) {
String name = (String)var7.next();
try {
Class<?> instanceClass = ClassUtils.forName(name, classLoader);
Assert.isAssignable(type, instanceClass);
Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);
T instance = BeanUtils.instantiateClass(constructor, args);
instances.add(instance);
} catch (Throwable var12) {
throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, var12);
}
}
return instances;
}
各个Initializer作用
创建listeners
listeners与initiazer类似,只不过类型改为ApplicationListener,spring.factories文件中值以下代码所示,返回结果为1
2
3
4
5
6
7
8
9org.springframework.context.ApplicationListener=\
org.springframework.boot.builder.ParentContextCloserApplicationListener,\
org.springframework.boot.context.FileEncodingApplicationListener,\
org.springframework.boot.context.config.AnsiOutputApplicationListener,\
org.springframework.boot.context.config.ConfigFileApplicationListener,\
org.springframework.boot.context.config.DelegatingApplicationListener,\
org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener,\
org.springframework.boot.logging.ClasspathLoggingApplicationListener,\
org.springframework.boot.logging.LoggingApplicationListener
以上Listener作用
推断main方法所在类,通过获取当前调用栈,找到入口方法main所在的类,并将其复制给SpringApplication对象的成员变量mainApplicationClass。
1 | private Class<?> deduceMainApplicationClass() { |
SpringApplication run()方法
1 | public ConfigurableApplicationContext run(String... args) { |
加载Listeners
1 | private SpringApplicationRunListeners getRunListeners(String[] args) { |
与以上加载initialazer类似,类名改为SpringApplicationRunListener,springfactories配置
1 | org.springframework.boot.SpringApplicationRunListener=\ |
EventPublishingRunListener作用
1 | //EventPublishingRunListener 类方法,该类实现SpringApplicationRunListener 接口 |
listener.onApplicationEvent 方法与SpringApplication成员属性对应
1 | // ParentContextCloserApplicationListener |
自定义ApplicationListener,用于初始化后执行特定方法原理
创建JavaBean实现ApplicationListener
prepareEnvironment方法
在Context创建前准备环境
1 | //SpringApplication |
listeners.environmentPrepared((ConfigurableEnvironment)environment)方法
1 | //SpringApplicationRunListeners |
上面代码创建ApplicationEnvironmentPreparedEvent,ConfigFileApplicationListener监听响应这个事件
1 | //ConfigFileApplicationListener |
加载EnvironmentPostProcessor
1 |
|
LoggingApplicationListener同样响应这个事件,对LogbackLoggingSystem初始化工作,具体未知
1 | // LoggingApplicationListener 加载log日志打印,具体未知 |
createApplicationContext() 创建上下文,判断是否为web环境,通常为web项目,只分析web环境及返回AnnotationConfigEmbeddedWebApplicationContext
1 |
|
AnnotationConfigEmbeddedWebApplicationContext 类图如下所示
AnnotationConfigEmbeddedWebApplicationContext构造方法如下 ,通过以下代码得知,只是为成员变量赋值1
2
3
4public AnnotationConfigEmbeddedWebApplicationContext() {
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
AnnotatedBeanDefinitionReader 解析并读取BeanDefinition
ClassPathBeanDefinitionScanner 用于扫描classpath目录下带注解的beanclass
接着上面prepareContext方法
1 |
|
listeners.contextPrepared(context)方法
1 | //SpringApplicationRunListeners |
isteners.contextLoaded(context);
1 | //SpringApplicationRunListeners |