最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Springboot的啟動原理詳細(xì)解讀

 更新時間:2023年11月08日 10:35:24   作者:你就像甜甜的益達(dá)  
這篇文章主要介紹了Springboot的啟動原理詳細(xì)解讀,springboot項(xiàng)目一般都是打包成jar包直接運(yùn)行main方法啟動,當(dāng)然也可以跟傳統(tǒng)的項(xiàng)目一樣打包war包放在tomcat里面啟動.那么springboot怎么直接通過main方法啟動呢,需要的朋友可以參考下

springboot主函數(shù)

springboot項(xiàng)目一般都是打包成jar包直接運(yùn)行main方法啟動,當(dāng)然也可以跟傳統(tǒng)的項(xiàng)目一樣打包war包放在tomcat里面啟動.那么springboot怎么直接通過main方法啟動呢?

舉個栗子,這是一個簡單的main方法啟動類:

@EnableAsync
@EnableScheduling
@EnableTransactionManagement
@EnableConfigurationProperties
@EnableCaching
@MapperScan(value = {"com.study.springbootplus.**.mapper"})
@SpringBootApplication
public class SpringBootPlusApplication {

  public static void main(String[] args) {
    ConfigurableApplicationContext context = SpringApplication.run(SpringBootPlusApplication.class, args);
  }

}

main方法

main方法主要就是看SpringApplication的run方法,這個方法大概就是創(chuàng)建個spring容器,然后創(chuàng)建個web容器(tomcat,jetty等)啟動.

run方法點(diǎn)進(jìn)去,這里一個新建springApplication實(shí)例,一個run方法:

	public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
		return new SpringApplication(primarySources).run(args);
	}

初始化SpringApplication實(shí)例

源碼:

	public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
		this.resourceLoader = resourceLoader;
		Assert.notNull(primarySources, "PrimarySources must not be null");
		// main方法中的args參數(shù),可接收命令行啟動時添加的參數(shù)
		this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
		// 確認(rèn)spring容器類型
		this.webApplicationType = WebApplicationType.deduceFromClasspath();
		//加載ApplicationContextInitializer類,ApplicationContext初始化類
		setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
		//加載ApplicationListener類,監(jiān)聽類
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
		//獲取main方法所在類
		this.mainApplicationClass = deduceMainApplicationClass();
	}

	private Class<?> deduceMainApplicationClass() {
		try {
			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;
	}

SpringApplication.run方法

源碼:

public ConfigurableApplicationContext run(String... args) {
//計(jì)時
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		//spring容器
		ConfigurableApplicationContext context = null;
		//錯誤回調(diào)
		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
		//設(shè)置一些系統(tǒng)屬性
		configureHeadlessProperty();
		//獲取啟動時監(jiān)聽器
		SpringApplicationRunListeners listeners = getRunListeners(args);
		//啟動監(jiān)聽器
		listeners.starting();
		try {
		//獲取一些啟動參數(shù)
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
			//創(chuàng)建運(yùn)行環(huán)境environment
			ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
			//設(shè)置一些系統(tǒng)參數(shù)
			configureIgnoreBeanInfo(environment);
			//打印banner
			Banner printedBanner = printBanner(environment);
			//創(chuàng)建spring容器
			context = createApplicationContext();
			//獲取異常報(bào)告,回調(diào)
			exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
					new Class[] { ConfigurableApplicationContext.class }, context);
					//準(zhǔn)備容器
			prepareContext(context, environment, listeners, applicationArguments, printedBanner);
			//刷新容器
			refreshContext(context);
			//spring容器后置處理
			afterRefresh(context, applicationArguments);
			//計(jì)時終止
			stopWatch.stop();
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
			}
			//結(jié)束通知
			listeners.started(context);
			//執(zhí)行runner
			callRunners(context, applicationArguments);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, listeners);
			throw new IllegalStateException(ex);
		}

		try {
		//spring容器就緒通知
			listeners.running(context);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, null);
			throw new IllegalStateException(ex);
		}
		//返回容器
		return context;
	}

getRunListeners方法,starting方法,獲取啟動監(jiān)聽,和啟動

源碼:

	private SpringApplicationRunListeners getRunListeners(String[] args) {
		Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
		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
		Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
		List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
		AnnotationAwareOrderComparator.sort(instances);
		return instances;
	}

前面講過啟動的時候會先加載spring會加載所有jar包下的META-INF/spring.factories,然后緩存起來,這里就獲取

在這里插入圖片描述

返回spirngboot唯一實(shí)現(xiàn)SpringApplicationRunListener的接口:EventPublishingRunListener,然后執(zhí)行starting方法;starting方法就是構(gòu)建ApplicationStartingEvent,然后獲取listener執(zhí)行,這一塊其實(shí)還比較復(fù)雜.用到了適配器模式:

在這里插入圖片描述

prepareEnvironment準(zhǔn)備環(huán)境

//準(zhǔn)備啟動參數(shù)就不說了
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);


	private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,
			ApplicationArguments applicationArguments) {
		// Create and configure the environment
		//創(chuàng)建一個environment對象
		ConfigurableEnvironment environment = getOrCreateEnvironment();
		//配置環(huán)境 PropertySources Profiles
		configureEnvironment(environment, applicationArguments.getSourceArgs());
		//PropertySources
		ConfigurationPropertySources.attach(environment);
		//環(huán)境準(zhǔn)備
		listeners.environmentPrepared(environment);
		//將環(huán)境綁定到oSpringApplication(
		bindToSpringApplication(environment);
		if (!this.isCustomEnvironment) {
			environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
					deduceEnvironmentClass());
		}
		//配置PropertySources-如果有attach到environment
		ConfigurationPropertySources.attach(environment);
		return environment;
	}

createApplicationContext創(chuàng)建容器

	protected ConfigurableApplicationContext createApplicationContext() {
		//獲取上下文的類
		Class<?> contextClass = this.applicationContextClass;
		if (contextClass == null) {
			try {
				switch (this.webApplicationType) {
					//判斷Web應(yīng)用類型
				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);
	}

在這里插入圖片描述

prepareContext,準(zhǔn)備容器

private void prepareContext(ConfigurableApplicationContext context, ConfigurableEnvironment environment,
			SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments, Banner printedBanner) {
			//設(shè)置環(huán)境
		context.setEnvironment(environment);
		//處理上下文
		postProcessApplicationContext(context);
		//獲取所有ApplicationContextInitializer,執(zhí)行ApplicationContextInitializer的init方法
		applyInitializers(context);
		//調(diào)用SpringApplicationRunListener的contextPrepared,表示容器已經(jīng)準(zhǔn)備
		listeners.contextPrepared(context);
		//日志
		if (this.logStartupInfo) {
			logStartupInfo(context.getParent() == null);
			logStartupProfileInfo(context);
		}
		// Add boot specific singleton beans
		//獲取beanfactory,注冊相關(guān)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);
		}
		//延遲加載
		if (this.lazyInitialization) {
			context.addBeanFactoryPostProcessor(new LazyInitializationBeanFactoryPostProcessor());
		}
		// Load the sources
		Set<Object> sources = getAllSources();
		Assert.notEmpty(sources, "Sources must not be empty");
		//加載啟動類
		load(context, sources.toArray(new Object[0]));
		//調(diào)用SpringApplicationRunListener的contextPrepared,表示容器已經(jīng)loaded事件
		listeners.contextLoaded(context);
	}

refreshContext,afterRefresh刷新容器,刷新容器之后執(zhí)行方法

就是spring容器的刷新方法

到此這篇關(guān)于Springboot的啟動原理詳細(xì)解讀的文章就介紹到這了,更多相關(guān)Springboot啟動原理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • IDEA插件FindBugs的使用詳解

    IDEA插件FindBugs的使用詳解

    這篇文章主要介紹了IDEA插件FindBugs的使用詳解,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-03-03
  • Java簡單實(shí)現(xiàn)動態(tài)代理模式過程解析

    Java簡單實(shí)現(xiàn)動態(tài)代理模式過程解析

    這篇文章主要介紹了Java動態(tài)代理模式簡單案例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-07-07
  • Java如何檢測當(dāng)前CPU負(fù)載狀態(tài)

    Java如何檢測當(dāng)前CPU負(fù)載狀態(tài)

    在Java中,直接檢測CPU負(fù)載狀態(tài)并不像在操作系統(tǒng)命令行中那樣簡單,因?yàn)镴ava標(biāo)準(zhǔn)庫并沒有直接提供這樣的功能,這篇文章主要介紹了java檢測當(dāng)前CPU負(fù)載狀態(tài)的方法,需要的朋友可以參考下
    2024-06-06
  • Java面向?qū)ο箢惡蛯ο髮?shí)例詳解

    Java面向?qū)ο箢惡蛯ο髮?shí)例詳解

    面向?qū)ο竽耸荍ava語言的核心,是程序設(shè)計(jì)的思想,這篇文章主要介紹了Java面向?qū)ο箢惡蛯ο蟮南嚓P(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-03-03
  • Java?Web實(shí)現(xiàn)簡易圖書管理系統(tǒng)

    Java?Web實(shí)現(xiàn)簡易圖書管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了Java?Web實(shí)現(xiàn)簡易圖書管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-09-09
  • Kafka日志清理實(shí)現(xiàn)詳細(xì)過程講解

    Kafka日志清理實(shí)現(xiàn)詳細(xì)過程講解

    這篇文章主要為大家介紹了Kafka日志清理實(shí)現(xiàn)詳細(xì)過程講解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05
  • springboot中如何使用openfeign進(jìn)行接口調(diào)用

    springboot中如何使用openfeign進(jìn)行接口調(diào)用

    這篇文章主要介紹了springboot中如何使用openfeign進(jìn)行接口調(diào)用問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • Java實(shí)現(xiàn)批量下載(打包成zip)的實(shí)現(xiàn)

    Java實(shí)現(xiàn)批量下載(打包成zip)的實(shí)現(xiàn)

    這篇文章主要介紹了Java實(shí)現(xiàn)批量下載(打包成zip)的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • spring?boot學(xué)習(xí)筆記之操作ActiveMQ指南

    spring?boot學(xué)習(xí)筆記之操作ActiveMQ指南

    ActiveMQ是一種開源的基于JMS規(guī)范的一種消息中間件的實(shí)現(xiàn),ActiveMQ的設(shè)計(jì)目標(biāo)是提供標(biāo)準(zhǔn)的,面向消息的,能夠跨越多語言和多系統(tǒng)的應(yīng)用集成消息通信中間件,這篇文章主要給大家介紹了關(guān)于spring?boot學(xué)習(xí)筆記之操作ActiveMQ指南的相關(guān)資料,需要的朋友可以參考下
    2021-11-11
  • 使用SpringBoot+MyBatis實(shí)現(xiàn)數(shù)據(jù)庫字段級加密

    使用SpringBoot+MyBatis實(shí)現(xiàn)數(shù)據(jù)庫字段級加密

    你是否曾經(jīng)為用戶敏感數(shù)據(jù)的安全存儲而頭疼?是否擔(dān)心數(shù)據(jù)庫一旦泄露就會造成巨大損失?今天,我要分享一個既優(yōu)雅又實(shí)用的解決方案——使用Spring Boot + MyBatis實(shí)現(xiàn)數(shù)據(jù)庫字段級加密,讓你的敏感數(shù)據(jù)固若金湯,需要的朋友可以參考下
    2026-01-01

最新評論

三门县| 庄河市| 阆中市| 达尔| 荥阳市| 张北县| 定日县| 开江县| 进贤县| 颍上县| 汤阴县| 名山县| 佛冈县| 南靖县| 阿克苏市| 衡阳市| 措美县| 东方市| 丰台区| 水城县| 社旗县| 馆陶县| 永胜县| 宁德市| 赤壁市| 团风县| 夹江县| 扶沟县| 招远市| 大庆市| 南康市| 青田县| 巴彦淖尔市| 荥经县| 华宁县| 鲁山县| 杭锦旗| 方城县| 南汇区| 庄河市| 石首市|