溫馨提示×

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

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

springBoot自動(dòng)注入原理的示例分析

發(fā)布時(shí)間:2022-03-03 14:47:42 來(lái)源:億速云 閱讀:176 作者:小新 欄目:開(kāi)發(fā)技術(shù)

這篇文章給大家分享的是有關(guān)springBoot自動(dòng)注入原理的示例分析的內(nèi)容。小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過(guò)來(lái)看看吧。

    @SpringBootApplication注解解讀

    為什么我們的啟動(dòng)類上標(biāo)注一個(gè)@SpringBootApplication注解,再加一個(gè)run()方法就可運(yùn)行起來(lái),可以看出我們的@SpringBootApplication注解是多么的強(qiáng)大。

    @SpringBootApplication
    public class App {
        public static void main(String[] args) {
            SpringApplication.run(App.class, args);
        }
    }

    @SpringBootApplication其實(shí)是由三個(gè)字注解來(lái)合成的。我們可以完全用這個(gè)三個(gè)注解來(lái)替換掉@SpringBootApplication。

    @SpringBootConfiguration
    @EnableAutoConfiguration
    @ComponentScan(excludeFilters = { @ComponentScan.Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
            @ComponentScan.Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
    public class App {
        public static void main(String[] args) {
            SpringApplication.run(App.class, args);
        }
    }

    我們來(lái)說(shuō)下這三個(gè)注解的一個(gè)作用,分別做了什么事情,為什么區(qū)區(qū)幾個(gè)注解就可以讓我們的程序跑起來(lái)。

    1.@SpringBootConfiguration

    其實(shí)點(diǎn)擊進(jìn)去就是一個(gè) @Configuration,沒(méi)什么特別的,學(xué)習(xí)過(guò)spring的朋友都知道,這是用于標(biāo)注一個(gè)配置類的。

    2.@EnableAutoConfiguration

    重點(diǎn)就是在于@EnableAutoConfiguration 這個(gè)注解,我們先看下他的一個(gè)構(gòu)成。

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @AutoConfigurationPackage
    @Import(AutoConfigurationImportSelector.class)
    public @interface EnableAutoConfiguration {

    @Inherited

    @Inherited : 如果標(biāo)注此注解標(biāo)識(shí)子類也可以進(jìn)行繼承,這個(gè)不太重要

    我們先來(lái)看.@EnableAutoConfiguration 注解中的@AutoConfigurationPackage注解里面的內(nèi)容有什么 ? 可以看到導(dǎo)入了一個(gè)AutoConfigurationPackages.Registrar類型的組件

    @AutoConfigurationPackage

    @AutoConfigurationPackage:

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @Import(AutoConfigurationPackages.Registrar.class)
    public @interface AutoConfigurationPackage {

    我們來(lái)看下導(dǎo)入的這個(gè)AutoConfigurationPackages.Registrar組件做了什么事情?

    registerBeanDefinitions? registerBeanDefinitions是不是就是往我們的容器中添加組件???那我們來(lái)看看他具體導(dǎo)入了那些組件。你可以將斷點(diǎn)打在這兩個(gè)方法上

    	static class Registrar implements ImportBeanDefinitionRegistrar, DeterminableImports {
    
    		@Override
    		public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
    			register(registry, new PackageImports(metadata).getPackageNames().toArray(new String[0]));
    		}
    
    		@Override
    		public Set<Object> determineImports(AnnotationMetadata metadata) {
    			return Collections.singleton(new PackageImports(metadata));
    		}
    
    	}

    springBoot自動(dòng)注入原理的示例分析

    只要把BeanDefinition注冊(cè)進(jìn)去,往后我們只要調(diào)用getBean()就會(huì)得到該對(duì)象,當(dāng)然不一定得我們自己調(diào)用,spring在底層最后刷新容器的時(shí)候,就會(huì)初始化所有的單實(shí)例bean,這也就是為什么我們直接使用相關(guān)注解就可以獲取到該對(duì)象的原有。

    getBean()有兩層意思:

    1.容器中有直接從緩存中獲取

    2.容器中沒(méi)有直接創(chuàng)建一個(gè),也就是走bean的生命周期創(chuàng)建

    AutoConfigurationImportSelector.class

    @Import(AutoConfigurationImportSelector.class) 核心組件,我們來(lái)看看他做了什么事情。

    AutoConfigurationImportSelector他呢繼承了DeferredImportSelector,DeferredImportSelector他呢有個(gè)內(nèi)部接口Group,而Group中又有個(gè)方法process()
    所以我們來(lái)到AutoConfigurationImportSelector中的process()方法打上斷點(diǎn)進(jìn)行觀察

    	@Override
    		public void process(AnnotationMetadata annotationMetadata, DeferredImportSelector deferredImportSelector) {
    			Assert.state(deferredImportSelector instanceof AutoConfigurationImportSelector,
    					() -> String.format("Only %s implementations are supported, got %s",
    							AutoConfigurationImportSelector.class.getSimpleName(),
    							deferredImportSelector.getClass().getName()));
    			AutoConfigurationEntry autoConfigurationEntry = ((AutoConfigurationImportSelector) deferredImportSelector)
    					.getAutoConfigurationEntry(annotationMetadata);
    			this.autoConfigurationEntries.add(autoConfigurationEntry);
    			for (String importClassName : autoConfigurationEntry.getConfigurations()) {
    				this.entries.putIfAbsent(importClassName, annotationMetadata);
    			}
    		}

    這個(gè)方法一上來(lái)就要獲取一些自動(dòng)注入的條目autoConfigurationEntry,那我們看下他是怎么獲取的,獲取的究竟是什么東西?
    通過(guò)堆棧信息我們可以看到是通過(guò)invokeBeanDefinitionRegistryPostProcessors()這個(gè)方法調(diào)用過(guò)來(lái)的,說(shuō)明在工廠初始化完畢,你可以往里面仍一些bean的定義信息了。

    進(jìn)去就是這個(gè)方法

    	protected AutoConfigurationEntry getAutoConfigurationEntry(AnnotationMetadata annotationMetadata) {
    		if (!isEnabled(annotationMetadata)) {
    			return EMPTY_ENTRY;
    		}
    		AnnotationAttributes attributes = getAttributes(annotationMetadata);
    		List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
    		configurations = removeDuplicates(configurations);
    		Set<String> exclusions = getExclusions(annotationMetadata, attributes);
    		checkExcludedClasses(configurations, exclusions);
    		configurations.removeAll(exclusions);
    		configurations = getConfigurationClassFilter().filter(configurations);
    		fireAutoConfigurationImportEvents(configurations, exclusions);
    		return new AutoConfigurationEntry(configurations, exclusions);
    	}

    我們?cè)龠M(jìn)入這個(gè)方法

    springBoot自動(dòng)注入原理的示例分析

    在進(jìn)入loadFactoryNames()方法中

    springBoot自動(dòng)注入原理的示例分析

    那我們?nèi)タ纯催@個(gè)文件里面有什么

    springBoot自動(dòng)注入原理的示例分析

    結(jié)合上面的代碼他是不是要加載org.springframework.boot.autoconfigure.EnableAutoConfiguration里面的內(nèi)容,這些就是一些配置類的信息

    其實(shí)這個(gè)文件 spring.factories 里面的每一個(gè)類的權(quán)限的名稱就是一個(gè)配置類,只不過(guò)springBoot把這些配置類都寫好了,在我們某些場(chǎng)景需要的時(shí)候直接給你注入就行,這就說(shuō)明了我們不用寫那么多配置文件的原因。

    我隨便點(diǎn)擊一個(gè)類進(jìn)去看看

    springBoot自動(dòng)注入原理的示例分析

    加載完成后: 怎么多?是不是全部第用得上啊?

    springBoot自動(dòng)注入原理的示例分析

    你看下面的代碼,是不是要排除,移除掉,過(guò)濾掉一些啊,排除就是我們自己在注解中寫的排除屬性進(jìn)行排除,讓后就是經(jīng)過(guò)一系列的篩選過(guò)濾。

    springBoot自動(dòng)注入原理的示例分析

    最后將這些信息put到entries中

    springBoot自動(dòng)注入原理的示例分析

    springBoot自動(dòng)注入原理的示例分析

    3.@ComponentScan

    @ComponentScan這個(gè)注解的功能就是掃描當(dāng)前類上標(biāo)注此注解所在包路徑的所有類,這也就是為什么我們需要把主啟動(dòng)類放在最外面的原有,如果你想把配置類放在別的地方,那你就得自己手動(dòng)指定包掃描路徑.

    感謝各位的閱讀!關(guān)于“springBoot自動(dòng)注入原理的示例分析”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!

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

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

    AI