这样深度Spring Boot的源码解析,看完帮你立即提升一个台阶!
Posted 程序员涨薪基地
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了这样深度Spring Boot的源码解析,看完帮你立即提升一个台阶!相关的知识,希望对你有一定的参考价值。
1 实例化SpringApplication
SpringApplication.run(BootifulApplication.class, 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); //new SpringApplication
}
public SpringApplication(Class<?>... primarySources) {
this(null, primarySources);
}
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
//设置资源加载器为null
this.resourceLoader = resourceLoader;
//断言加载资源类不能为null
Assert.notNull(primarySources, "PrimarySources must not be null");
//将primarySources数组转换为List,最后放到LinkedHashSet集合中
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
//【1.1 推断当前应用类型是否为WEB】
this.webApplicationType = WebApplicationType.deduceFromClasspath();
//【1.2 设置应用上下文初始化器】
setInitializers((Collection) getSpringFactoriesInstances(
ApplicationContextInitializer.class));
//【1.3 设置监听器】
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
//【1.4 推断应用的入口类】
this.mainApplicationClass = deduceMainApplicationClass();
}
1.1 推断当前应用类型是否为WEB
根据classpath下的内容推断出应用的类型
this.webApplicationType = WebApplicationType.deduceFromClasspath();
static WebApplicationType deduceFromClasspath() {
if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null)
&& !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
&& !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
return WebApplicationType.REACTIVE;
}
for (String className : SERVLET_INDICATOR_CLASSES) {
if (!ClassUtils.isPresent(className, null)) {
return WebApplicationType.NONE;
}
}
return WebApplicationType.SERVLET;
}
1.2 设置应用上下文初始化器
setInitializers((Collection)getSpringFactoriesInstances(ApplicationContextInitializer.class));
ApplicationContextInitializer
public interface ApplicationContextInitializer<C extends ConfigurableApplicationContext> {
/**
* Initialize the given application context.
* @param applicationContext the application to configure
*/
void initialize(C applicationContext);
}
getSpringFactoriesInstances(ApplicationContextInitializer.class)
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 = getClassLoader();
// Use names and ensure unique to protect against duplicates
//获取ApplicationContextInitializer实例名称并且去重
Set<String> names = new LinkedHashSet<>(
//进入loadFactoryNames方法并且找到loadSpringFactories---spring.factories
SpringFactoriesLoader.loadFactoryNames(type, classLoader));
//创建初始化器实例列表
List<T> instances = createSpringFactoriesInstances(type, parameterTypes,
classLoader, args, names);
//排序
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
setInitializers(...)
初始化一个ApplicationContextInitializer
public void setInitializers(
Collection<? extends ApplicationContextInitializer<?>> initializers) {
this.initializers = new ArrayList<>();
this.initializers.addAll(initializers);
}
1.3 设置监听器
setListeners((Collection)getSpringFactoriesInstances(ApplicationListener.class));
ApplicationListener
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {
/**
* Handle an application event.
* @param event the event to respond to
*/
void onApplicationEvent(E event);
}
getSpringFactoriesInstances(ApplicationListener.class)
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 = getClassLoader();
// Use names and ensure unique to protect against duplicates
//获取ApplicationContextInitializer实例名称并且去重
Set<String> names = new LinkedHashSet<>(
//进入loadFactoryNames方法并且找到loadSpringFactories---spring.factories
SpringFactoriesLoader.loadFactoryNames(type, classLoader));
List<T> instances = createSpringFactoriesInstances(type, parameterTypes,
classLoader, args, names);
//创建初始化器实例列表
AnnotationAwareOrderComparator.sort(instances);
//排序
return instances;
}
setListeners(...)
初始化一个ApplicationListener
public void setListeners(Collection<? extends ApplicationListener<?>> listeners) {
this.listeners = new ArrayList<>();
this.listeners.addAll(listeners);
}
1.4 推断应用的入口类
this.mainApplicationClass = deduceMainApplicationClass();
private Class<?> deduceMainApplicationClass() {
try {
//构造一个运行时异常,遍历异常栈中的方法名,获取方法名为main的栈帧,得到入口类的名字再返回该类
StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
for (StackTraceElement stackTraceElement : stackTrace) {
if ("main".equals(stackTraceElement.getMethodName())) {
return Class.forName(stackTraceElement.getClassName());
}
}
}
catch (ClassNotFoundException ex) {
// Swallow and continue
}
return null;
}
2 调用run方法
/**
* Run the Spring application, creating and refreshing a new
* {@link ApplicationContext}.
* @param args the application arguments (usually passed from a Java main method)
* @return a running {@link ApplicationContext}
*/
public ConfigurableApplicationContext run(String... args) {
//创建计时类
StopWatch stopWatch = new StopWatch();
stopWatch.start();
//初始化应用上下文和异常报告集合
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
//设置headless属性
configureHeadlessProperty();
//【2.1 创建运行监听器】
SpringApplicationRunListeners listeners = getRunListeners(args);
//发布应用启动事件
listeners.starting();
try {
//初始化默认应用参数类
ApplicationArguments applicationArguments = new DefaultApplicationArguments(
args);
//【2.2 根据监听器和应用参数类准备Spring环境】
ConfigurableEnvironment environment = prepareEnvironment(listeners,
applicationArguments);
configureIgnoreBeanInfo(environment);
//创建Banner打印类
Banner printedBanner = printBanner(environment);
//【2.3 创建应用上下文】
context = createApplicationContext();
//准备异常报告
exceptionReporters = getSpringFactoriesInstances(
SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
//【2.4 准备应用上下文】
prepareContext(context, environment, listeners, applicationArguments,
printedBanner);
//【2.5 刷新应用上下文】
refreshContext(context);
//应用上下文后置处理刷新
afterRefresh(context, applicationArguments);
//停止计时类
stopWatch.stop();
//输出日志记录执行主类名、时间信息
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass)
.logStarted(getApplicationLog(), stopWatch);
}
//发布应用上下文启动完成事件
listeners.started(context);
//【2.6 执行Runner运行器】
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
//发布应用上下文就绪事件
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
//返回应用上下文
return context;
}
2.1 创建运行监听器
SpringApplicationRunListeners listeners = getRunListeners(args);
private SpringApplicationRunListeners getRunListeners(String[] args) {
Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
return new SpringApplicationRunListeners(logger, getSpringFactoriesInstances(
SpringApplicationRunListener.class, types, this, args));
}
SpringApplicationRunListener
org.springframework.boot:spring-boot/META-INF/spring.factories
getSpringFactoriesInstances(...)
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type,
Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = getClassLoader();
// Use names and ensure unique to protect against duplicates
Set<String> names = new LinkedHashSet<>(
SpringFactoriesLoader.loadFactoryNames(type, classLoader));
List<T> instances = createSpringFactoriesInstances(type, parameterTypes,
classLoader, args, names);
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
new SpringApplicationRunListeners(...)
SpringApplicationRunListeners(Log log,
Collection<? extends SpringApplicationRunListener> listeners) {
this.log = log;
this.listeners = new ArrayList<>(listeners);
}
2.2 根据监听器和应用参数类准备Spring环境
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
private ConfigurableEnvironment prepareEnvironment(
SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments) {
// Create and configure the environment
//获取应用环境(3种情况)
ConfigurableEnvironment environment = getOrCreateEnvironment();
//配置应用环境
configureEnvironment(environment, applicationArguments.getSourceArgs());
listeners.environmentPrepared(environment);
bindToSpringApplication(environment);
if (!this.isCustomEnvironment) {
environment = new EnvironmentConverter(getClassLoader())
.convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());
}
ConfigurationPropertySources.attach(environment);
return environment;
}
2.3 创建应用上下文
context = createApplicationContext();
protected ConfigurableApplicationContext createApplicationContext() {
Class<?> contextClass = this.applicationContextClass;
if (contextClass == null) {
try {
switch (this.webApplicationType) {
case SERVLET:
contextClass = Class.forName(DEFAULT_SERVLET_WEB_CONTEXT_CLASS);
break;
case REACTIVE:
contextClass = Class.forName(DEFAULT_REACTIVE_WEB_CONTEXT_CLASS);
break;
default:
contextClass = Class.forName(DEFAULT_CONTEXT_CLASS);
}
}
catch (ClassNotFoundException ex) {
throw new IllegalStateException(
"Unable create a default ApplicationContext, "
+ "please specify an ApplicationContextClass",
ex);
}
}
return (ConfigurableApplicationContext) BeanUtils.instantiateClass(contextClass);
}
2.4 准备应用上下文
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
private void prepareContext(ConfigurableApplicationContext context,
ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,
ApplicationArguments applicationArguments, Banner printedBanner) {
//绑定环境到上下文
context.setEnvironment(environment);
//配置上下文的bean生成器和资源加载器
postProcessApplicationContext(context);
//为上下文采用所有初始化器
applyInitializers(context);
//触发监听器的contextPrepared事件
listeners.contextPrepared(context);
//记录启动日志
if (this.logStartupInfo) {
logStartupInfo(context.getParent() == null);
logStartupProfileInfo(context);
}
// Add boot specific singleton beans
//注册两个特殊的单例Bean
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
beanFactory.registerSingleton("springApplicationArguments", applicationArguments);
if (printedBanner != null) {
beanFactory.registerSingleton("springBootBanner", printedBanner);
}
if (beanFactory instanceof DefaultListableBeanFactory) {
((DefaultListableBeanFactory) beanFactory)
.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
}
// Load the sources
//加载所有资源
Set<Object> sources = getAllSources();
Assert.notEmpty(sources, "Sources must not be empty");
load(context, sources.toArray(new Object[0]));
//触发监听器的contextLoaded事件
listeners.contextLoaded(context);
}
2.5 刷新应用上下文
refreshContext(context);
private void refreshContext(ConfigurableApplicationContext context) {
refresh(context); //--->进入该方法
if (this.registerShutdownHook) {
try {
context.registerShutdownHook();
}
catch (AccessControlException ex) {
// Not allowed in some environments.
}
}
}
protected void refresh(ApplicationContext applicationContext) {
Assert.isInstanceOf(AbstractApplicationContext.class, applicationContext);
((AbstractApplicationContext) applicationContext).refresh(); //--->进入该方法
}
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
//context:启动日期|设置context当前状态|初始化环境|验证必须
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
//刷新内部bean工厂,即创建一个bean工厂(对BeanDefinition的定义、解析、处理和注册)
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
//上面创建好了之后,还需要配置一些东西才能使用
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
//注册WEB特性的scope(如request,session等)
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
//调用所有的bean工厂处理器对bean进行一些处理
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
//注册用来拦截bean
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
//主要用于国际化
initMessageSource();
// Initialize event multicaster for this context.
//为context初始化一个事件广播器
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
/*
在AbstractApplicationContext的子类中初始化其他特殊的bean。
其实就是初始化ThemeSource接口的实例。这个方法需要在所有单例bean初始化之前调用。
*/
onRefresh();
// Check for listener beans and register them.
//注册应用监听器
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
//完成对bean工厂初始化工作
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
//调用LifecycleProcessor的onRefresh()方法并且发布事件
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
2.6 执行Runner运行器
callRunners(context, applicationArguments);
执行所有ApplicationRunner和CommandLineRunner两种运行器
private void callRunners(ApplicationContext context, ApplicationArguments args) {
List<Object> runners = new ArrayList<>();
runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
AnnotationAwareOrderComparator.sort(runners);
for (Object runner : new LinkedHashSet<>(runners)) {
if (runner instanceof ApplicationRunner) {
callRunner((ApplicationRunner) runner, args);
}
if (runner instanceof CommandLineRunner) {
callRunner((CommandLineRunner) runner, args);
}
}
}
如果觉得文章不错,动动小手,转发转发!
以上是关于这样深度Spring Boot的源码解析,看完帮你立即提升一个台阶!的主要内容,如果未能解决你的问题,请参考以下文章
SpringBoot 源码解析 ----- Spring Boot 精髓:集成AOP