溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

使用Springboot怎么對(duì)路徑進(jìn)行掃描

發(fā)布時(shí)間:2020-12-21 15:35:35 來源:億速云 閱讀:314 作者:Leah 欄目:開發(fā)技術(shù)

使用Springboot怎么對(duì)路徑進(jìn)行掃描?相信很多沒有經(jīng)驗(yàn)的人對(duì)此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個(gè)問題。

我們暫且標(biāo)注下Springboot啟動(dòng)過程中較為重要的邏輯方法,源碼對(duì)應(yīng)的spring-boot-2.2.2.RELEASE版本

public ConfigurableApplicationContext run(String... args) {
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();
		ConfigurableApplicationContext context = null;
		Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
		configureHeadlessProperty();
		SpringApplicationRunListeners listeners = getRunListeners(args);
		listeners.starting();
		try {
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
			ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
			configureIgnoreBeanInfo(environment);
			Banner printedBanner = printBanner(environment);
			//@A
			context = createApplicationContext();
			exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
					new Class[] { ConfigurableApplicationContext.class }, context);
			//@B
			prepareContext(context, environment, listeners, applicationArguments, printedBanner);
			//@C
			refreshContext(context);
			afterRefresh(context, applicationArguments);
			stopWatch.stop();
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
			}
			listeners.started(context);
			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;
	}

第一步:ConfigurationClassPostProcessor注入

org.springframework.context.annotation.ConfigurationClassPostProcessor是一個(gè)BeanDefinitionRegistryPostProcessor(父類是BeanFactoryPostProcessor),會(huì)在容器初始化好并裝載完第一階段的bean定義后調(diào)用,我理解的其主要作用是執(zhí)行一些框架內(nèi)部方法也讓用戶自定義再次注入自定義的bean定義;

它的注冊是在SpringApplication.run方法調(diào)用后,具體調(diào)用鏈?zhǔn)?/p>

org.springframework.boot.SpringApplication#run(java.lang.Class<?>, java.lang.String...)
->org.springframework.boot.SpringApplication#run(java.lang.String...)
->org.springframework.boot.SpringApplication#createApplicationContext 
//對(duì)應(yīng)上面@A標(biāo)注的地方
//后續(xù)會(huì)初始化一個(gè)org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext對(duì)象,在構(gòu)造方法里會(huì)執(zhí)行一系列的邏輯
->org.springframework.context.annotation.AnnotatedBeanDefinitionReader#AnnotatedBeanDefinitionReader(org.springframework.beans.factory.support.BeanDefinitionRegistry)
->org.springframework.context.annotation.AnnotatedBeanDefinitionReader#AnnotatedBeanDefinitionReader(org.springframework.beans.factory.support.BeanDefinitionRegistry, org.springframework.core.env.Environment)
->org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(org.springframework.beans.factory.support.BeanDefinitionRegistry)
->org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.Object)

//這個(gè)方法會(huì)注入5個(gè)bean定義:
1. ConfigurationClassPostProcessor.class
2. AutowiredAnnotationBeanPostProcessor.class
3. CommonAnnotationBeanPostProcessor.class
4. EventListenerMethodProcessor.class
5. DefaultEventListenerFactory.class

第二步:啟動(dòng)類bean定義注入

被我們標(biāo)記了@SpringBootApplication的類在運(yùn)行過程中會(huì)被包裝成一個(gè)bean定義,放入容器中;具體方法調(diào)用鏈

org.springframework.boot.SpringApplication#run(java.lang.String...)
org.springframework.boot.SpringApplication#prepareContext //對(duì)應(yīng)上面代碼標(biāo)注 @B 的地方
org.springframework.boot.SpringApplication#load
org.springframework.boot.BeanDefinitionLoader#load(java.lang.Object)
org.springframework.boot.BeanDefinitionLoader#load(java.lang.Class<?>)
org.springframework.context.annotation.AnnotatedBeanDefinitionReader#register
org.springframework.context.annotation.AnnotatedBeanDefinitionReader#registerBean(java.lang.Class<?>)
org.springframework.context.annotation.AnnotatedBeanDefinitionReader#doRegisterBean

//里面一段代碼 如下:
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass);
//從這個(gè)方法里可以看出,啟動(dòng)類被包裝成了 AnnotatedGenericBeanDefinition(實(shí)現(xiàn)了AnnotatedBeanDefinition接口,這很重要)

第三步:解析包掃描信息并完成剩余bean注冊

剛剛在第一步里,容器中注入了ConfigurationClassPostProcessor后置處理器,后置處理器會(huì)在核心方法refresh中執(zhí)行,也就是上面標(biāo)注@C的代碼里;

我們直接來到核心邏輯處,調(diào)用鏈:

使用Springboot怎么對(duì)路徑進(jìn)行掃描

由于第二步容器中將啟動(dòng)類包裝成AnnotatedGenericBeanDefinition并注入了容器,在方法
org.springframework.context.annotation.ConfigurationClassParser#parse(java.util.Set<org.springframework.beans.factory.config.BeanDefinitionHolder>)會(huì)被處理執(zhí)行后續(xù)的包掃描

看完上述內(nèi)容,你們掌握使用Springboot怎么對(duì)路徑進(jìn)行掃描的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI