SpringBoot 啟動(dòng)方法run()源碼解析
入口
通常一個(gè)簡(jiǎn)單的SpringBoot基礎(chǔ)項(xiàng)目我們會(huì)有如下代碼
@SpringBootApplication
@RestController
@RequestMapping("/")
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
值得關(guān)注的有SpringApplication.run以及注解@SpringBootApplication
run方法
public ConfigurableApplicationContext run(String... args) {
// 秒表
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
configureHeadlessProperty();
// 獲取監(jiān)聽器
SpringApplicationRunListeners listeners = getRunListeners(args);
// 監(jiān)聽器啟動(dòng)
listeners.starting();
try {
// application 啟動(dòng)參數(shù)列表
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
// 配置忽略的bean信息
configureIgnoreBeanInfo(environment);
Banner printedBanner = printBanner(environment);
// 創(chuàng)建應(yīng)用上下文
context = createApplicationContext();
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
// 準(zhǔn)備上下文,裝配bean
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
// 上下文刷新
refreshContext(context);
// 刷新后做什么
afterRefresh(context, applicationArguments);
stopWatch.stop();
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
// 監(jiān)聽器開始了
listeners.started(context);
// 喚醒
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
// 監(jiān)聽器正式運(yùn)行
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}
getRunListeners
獲取監(jiān)聽器
private SpringApplicationRunListeners getRunListeners(String[] args) {
Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
// 獲取 Spring Factory 實(shí)例對(duì)象
return new SpringApplicationRunListeners(logger,
getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
}
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = getClassLoader();
// Use names and ensure unique to protect against duplicates
// 讀取 spring.factories
Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
// 創(chuàng)建SpringFactory實(shí)例
List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
/**
* 排序 {@link Ordered}
*/
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
createSpringFactoriesInstances
@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 {
// 通過(guò)名字創(chuàng)建類的class對(duì)象
Class<?> instanceClass = ClassUtils.forName(name, classLoader);
Assert.isAssignable(type, instanceClass);
// 構(gòu)造器獲取
Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);
// 創(chuàng)建具體實(shí)例
T instance = (T) BeanUtils.instantiateClass(constructor, args);
// 加入實(shí)例表中
instances.add(instance);
}
catch (Throwable ex) {
throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, ex);
}
}
return instances;
}
printBanner
private Banner printBanner(ConfigurableEnvironment environment) {
if (this.bannerMode == Banner.Mode.OFF) {
return null;
}
ResourceLoader resourceLoader = (this.resourceLoader != null) ? this.resourceLoader
: new DefaultResourceLoader(getClassLoader());
// 創(chuàng)建打印器
SpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBannerPrinter(resourceLoader, this.banner);
if (this.bannerMode == Mode.LOG) {
// 輸出
return bannerPrinter.print(environment, this.mainApplicationClass, logger);
}
// 輸出
return bannerPrinter.print(environment, this.mainApplicationClass, System.out);
}
Banner print(Environment environment, Class<?> sourceClass, PrintStream out) {
Banner banner = getBanner(environment);
banner.printBanner(environment, sourceClass, out);
return new PrintedBanner(banner, sourceClass);
}
最終輸出內(nèi)容類:org.springframework.boot.SpringBootBanner
class SpringBootBanner implements Banner {
private static final String[] BANNER = { "", " . ____ _ __ _ _",
" /\\\\ / ___'_ __ _ _(_)_ __ __ _ \\ \\ \\ \\", "( ( )\\___ | '_ | '_| | '_ \\/ _` | \\ \\ \\ \\",
" \\\\/ ___)| |_)| | | | | || (_| | ) ) ) )", " ' |____| .__|_| |_|_| |_\\__, | / / / /",
" =========|_|==============|___/=/_/_/_/" };
private static final String SPRING_BOOT = " :: Spring Boot :: ";
private static final int STRAP_LINE_SIZE = 42;
@Override
public void printBanner(Environment environment, Class<?> sourceClass, PrintStream printStream) {
for (String line : BANNER) {
printStream.println(line);
}
String version = SpringBootVersion.getVersion();
version = (version != null) ? " (v" + version + ")" : "";
StringBuilder padding = new StringBuilder();
while (padding.length() < STRAP_LINE_SIZE - (version.length() + SPRING_BOOT.length())) {
padding.append(" ");
}
printStream.println(AnsiOutput.toString(AnsiColor.GREEN, SPRING_BOOT, AnsiColor.DEFAULT, padding.toString(),
AnsiStyle.FAINT, version));
printStream.println();
}
}
希望通過(guò)本篇對(duì)于springboot啟動(dòng)方法的解讀,讓大家對(duì)springboot底層有了一個(gè)大致了解,只分析了主要方法,希望對(duì)大家有幫助
到此這篇關(guān)于SpringBoot 啟動(dòng)方法run()源碼賞析的文章就介紹到這了,更多相關(guān)SpringBoot 啟動(dòng)run()內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
idea注解參數(shù)換行時(shí)間日期格式設(shè)置方法
這篇文章主要介紹了idea注解參數(shù)換行時(shí)間日期格式設(shè)置方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-05-05
Java編程發(fā)展歷史(動(dòng)力節(jié)點(diǎn)Java學(xué)院整理)
Java的歷史可以追溯到1991年4月,Sun公司的James Gosling領(lǐng)導(dǎo)的綠色計(jì)劃(Green Project)開始著力發(fā)展一種分布式系統(tǒng)結(jié)構(gòu),使其能夠在各種消費(fèi)性電子產(chǎn)品上運(yùn)行,他們使用了C/C++/Oak語(yǔ)言。由于多種原因,綠色計(jì)劃逐漸陷于停滯狀態(tài)2017-03-03
Spring事務(wù)管理中關(guān)于數(shù)據(jù)庫(kù)連接池詳解
事務(wù)的作用就是為了保證用戶的每一個(gè)操作都是可靠的,事務(wù)中的每一步操作都必須成功執(zhí)行,只要有發(fā)生異常就 回退到事務(wù)開始未進(jìn)行操作的狀態(tài)。事務(wù)管理是Spring框架中最為常用的功能之一,我們?cè)谑褂肧pring Boot開發(fā)應(yīng)用時(shí),大部分情況下也都需要使用事務(wù)2022-12-12
Spring BeanFactory和FactoryBean有哪些區(qū)別
這篇文章主要介紹了Spring BeanFactory 與 FactoryBean 的區(qū)別詳情,BeanFactory 和 FactoryBean 的區(qū)別卻是一個(gè)很重要的知識(shí)點(diǎn),在本文中將結(jié)合源碼進(jìn)行分析講解,需要的小伙伴可以參考一下2023-02-02
Eclipse下編寫java程序突然不會(huì)自動(dòng)生成R.java文件和包的解決辦法
這篇文章主要介紹了Eclipse下編寫java程序突然不會(huì)自動(dòng)生成R.java文件和包的解決辦法 的相關(guān)資料,需要的朋友可以參考下2016-01-01
SpringCloud分布式事務(wù)Seata部署和集成過(guò)程
這篇文章主要介紹了SpringCloud分布式事務(wù)Seata部署和集成過(guò)程,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-10-10
Spring Boot實(shí)現(xiàn)STOMP協(xié)議的WebSocket的方法步驟
這篇文章主要介紹了Spring Boot實(shí)現(xiàn)STOMP協(xié)議的WebSocket的方法步驟,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-05-05

