您好,登錄后才能下訂單哦!
使用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)用鏈:
由于第二步容器中將啟動(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è)資訊頻道,感謝各位的閱讀!
免責(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)容。