转载

这样深度Spring Boot的源码解析,看完帮你立即提升一个台阶!

这样深度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的源码解析,看完帮你立即提升一个台阶!

如果觉得文章不错,动动小手,转发转发!

原文  http://mp.weixin.qq.com/s?__biz=MzUzODU4MjE2MQ==&mid=2247484048&idx=1&sn=76685a6deddf0812a15b9012b36f650a
正文到此结束
Loading...