亚洲精品中文免费|亚洲日韩中文字幕制服|久久精品亚洲免费|一本之道久久免费

      
      

            <dl id="hur0q"><div id="hur0q"></div></dl>

                深入理解springboot的自動注入

                深入理解springboot的自動注入

                一、開篇

                ??在平時的開發(fā)過程中用的最多的莫屬springboot了,都知道springboot中有自動注入的功能,在面試過程中也會問到自動注入,你知道自動注入是怎么回事嗎,springboot是如何做到自動注入的,自動注入背后的原理是什么,今天來分析下springboot的自動注入,希望這篇文章可以解除大家心中的疑惑。

                二、詳述

                2.1、什么是自動注入

                ??天天將自動注入,你真正明白自動注入是怎么回事嗎?舉個例子來說,我們要在springboot中使用mybatis,之前的做法是什么?

                ??1、引入依賴;

                ??2、在配置文件中配置配置類;

                ??3、寫mybatis的配置文件或注解;

                ??在springboot中這個步驟就減少了,減少的是第二步,不用再寫一堆配置類了,步驟簡化為:

                ??1、引入依賴;

                ??2、寫mybatis的配置文件或注解;

                ??也就是說無需再搞配置類了,就比如之前的”SqlSessionFactoryBean“,現在不用配置了,springboot為我們做了這些工作,現在看springboot引入mybatis需要加入的依賴,

                org.mybatis.spring.boot mybatis-spring-boot-starter 2.1.3 mysql mysql-connector-java 8.0.26

                ??我們加入mybatis和數據庫的驅動依賴,因為mybatis要使用數據庫連接,所以這里少不了mysql的數據庫驅動。重點看mybatis的這個依賴和之前的是不一樣的,這個是”mybatis-spring-boot-starter“,再看這個依賴中都有哪些jar,

                ??除了常見的mybatis及mybatis-spring還有一個mybatis-spring-boot-autoconfigure,這個就是今天的主角。

                2.2、springboot讀取spring.facotries文件(可跳過該節(jié))

                ??前邊說到今天的主角是”mybatis-spring-boot-autoconfigure“,其實還有很多這樣的依賴,大多數第三方自己實現的都會有這樣一個依賴比如,前邊自己實現的starter中就有這樣一個”customer-spring-boot-autoconfigurer“,還有很多都是springboot自己實現的,所以無需這樣的依賴。

                ??要想知道springboot是如何進行自動注入的,唯一的方式是debug,現在開始debug之旅吧。

                2.2.1、SpringApplication構造方法

                ??springboot的啟動很簡單,就是下面這樣一行代碼

                SpringApplication.run(BootServer.class);

                ??要跟著這樣一行代碼走下去,追蹤到了這樣一句,

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

                ??可以看的會new一個SpringApplication的實例,然后再調用其run方法,先看下new方法做了什么,最終調用的是下面的構造方法,

                public SpringApplication(ResourceLoader resourceLoader, Class… primarySources) {this.resourceLoader = resourceLoader;Assert.notNull(primarySources, “PrimarySources must not be null”);this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));this.webApplicationType = WebApplicationType.deduceFromClasspath(); //設置初始化器,很重要setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class)); //設置監(jiān)聽器,很重要setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));this.mainApplicationClass = deduceMainApplicationClass();}

                ??我在上面 做了注釋,重點看注釋部分的代碼;

                2.2.2、setInitializers()方法

                ??該方法從方法名上看是要設置初始化器,其中getSpringFactoriesInstances(ApplicationContextInitializer.class)是重點。其方法定義如下,

                private Collection getSpringFactoriesInstances(Class type, Class[] parameterTypes, Object… args) {ClassLoader classLoader = getClassLoader();// Use names and ensure unique to protect against duplicates //SpringFactoriesLoader.loadFactoryNames是重點Set names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));List instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);AnnotationAwareOrderComparator.sort(instances);return instances;}

                ??看SpringFactoriesLoader.loadFactoryNames方法,

                public static List loadFactoryNames(Class factoryType, @Nullable ClassLoader classLoader) {String factoryTypeName = factoryType.getName(); //loadSpringFactories(classLoader)方法是重點return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());}

                ??把斷點放在loadSpringFactroies方法內,

                ??從上面的debug結果可以看到使用AppClassLoader讀取”FACTORIES_RESOURCE_LOCATION“處的資源,AppClassLoader大家都很熟悉,就說應用類加載器,常量”FACTORIES_RESOURCE_LOCATION“指的是,

                /** * The location to look for factories. *

                Can be present in multiple JAR files. */public static final String FACTORIES_RESOURCE_LOCATION = “META-INF/spring.factories”;

                ??jar下的”META-INF/spring.factories“文件,也就是說要讀取項目中jar包中的”META-INF/spring.factories“文件的內容,我在spring-boot-2.3.3.RELEASE.jar中找到這樣一個文件,僅截個圖,詳細內容可以自己查看,

                ??可以看到是一些列的鍵值對,我們看下loadSpringFactories方法最后的返回值,

                ??這個返回值是,項目中所有jar下META-INF/spring.factories文件中的鍵值對組成的map。回到loadFactoryNames方法處

                ??該方法需要的是key為”org.springframework.context.ApplicationContextInitializer“的value,該value的值有這樣7個

                這樣我們把setInitializers方法就分析完了,其主要就是從jar包中的META-INF/spring.factories文件中獲取org.springframework.context.ApplicationContextInitializer對應的值。下面看setListeners方法

                2.2.3、setListeners()方法

                ??該方法和setInitializers方法是類似的,

                ??重點是其參數不一樣,該方法的參數是ApplicationListener.class,也就是要找出org.springframework.context.ApplicationListener在spring.factories中的配置,

                ??本人核實過這些的確是從spring.factories文件中讀取的,和其內容是一致的。

                寫到這里其實和自動注入沒有關系,如果說有關系的話是,這里認識了一個關鍵的類”SpringFactoriesLoader“,該類的作用就是讀取jar包中META-INF/spring.facotries文件的內容。在后邊的自動注入中還會出現該類的影子。繼續(xù)向前。

                2.3、自動注入的原理

                2.3.1、@SpringBootApplication注解??

                在啟動springboot程序的時候在程序的入口都會有寫上@SpringBootApplication的注解,

                package com.my.template;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;/** * 啟動類 * @date 2022/6/3 21:32 */@SpringBootApplicationpublic class BootServer { public static void main(String[] args) { try { SpringApplication.run(BootServer.class); }catch (Exception e){ e.printStackTrace(); } }}

                ??看下該注解的定義,

                ??在該注解上還有@SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan三個注解,今天重點看@EnableAutoConfiguration注解。

                2.3.2、@EnableAutoConfiguration注解

                ??該注解便是自動注入的核心注解,

                ??重點是該注解上的下面這句話,

                @Import(AutoConfigurationImportSelector.class)

                ??看下AutoConfigurationImportSelector類,該類中有這樣一個方法,和自動注入是相關的,

                protected List getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {List configurations = SpringFactoriesLoader.loadFactoryNames(getSpringFactoriesLoaderFactoryClass(),getBeanClassLoader());Assert.notEmpty(configurations, “No auto configuration classes found in META-INF/spring.factories. If you “+ “are using a custom packaging, make sure that file is correct.”);return configurations;}

                很屬性的SpringFactoriesLoader類又出現了,還是很熟悉的loadFactoryNames方法,這次的方法參數是getSpringFactoriesLoaderFactoryClass()方法,

                /** * Return the class used by {@link SpringFactoriesLoader} to load configuration * candidates. * @return the factory class */protected Class getSpringFactoriesLoaderFactoryClass() {return EnableAutoConfiguration.class;}

                ??所以SpringFactoriesLoader.loadFactoryNames是要從META-INF/spring.factories中獲取key為”org.springframework.boot.autoconfigure.EnableAutoConfiguration“的value,這里可以看到有很多,從中還可以找到我自定義的和myatis的。

                也就是說要把這些配置類加到spring的容器中。現在有個問題這些配置都會生效嗎?

                2.3.3、這些配置類都會生效嗎?

                ??上面說到自動配置會加載很多的配置類,但是這些類都會生效嗎?答案是不會的,只會在特定情況下生效,以MybatisAutoConfiguration為例,

                ??可以看的該類上有很多注解,

                ??@ConditionalOnClass,當類路徑中存在某個類標識該注解的類才會生效,也就是只有存在SqlSessionFactory、SqlSessionFactoryBean才會解析MybatisAutoConfiguration類。換句話說,要有mybatis、mybatis-spring的jar包。

                ??@ConditionaleOnSigleCanidate,需要一個單例bean

                ??@EnableConfigurationProperties 讀取配置文件,也就是application.properites

                ??@AutoConfigureAfter 自動配置在某個類之后

                現在我們知道了一個XXAutoConfiguration類是否會生效還要看其上面的注解是怎么定義的。

                三、總結

                ??本文主要分析了springboot的自動注入原理,

                ??1、注解@SpringBootApplication中含有三個注解,其中@EnabelAutoConfiguration和自動配置有關;

                ??2、@EnableAutoConfiguration會讀取所有jar下META-INF/spring.factories文件的內容,獲取”org.springframework.boot.autoconfigure.EnableAutoConfiguration“的配置,把這些配置注入到容器;

                ??3、@EnableAutoConfiguration注入的類是否生效,需要看其上面的注解,主要配合@ConditionaleXXX注解使用;

                鄭重聲明:本文內容及圖片均整理自互聯網,不代表本站立場,版權歸原作者所有,如有侵權請聯系管理員(admin#wlmqw.com)刪除。
                用戶投稿
                上一篇 2022年6月27日 06:22
                下一篇 2022年6月27日 06:23

                相關推薦

                • 11月27日哈爾濱疫情最新消息:昨日新增本土85+183

                  黑龍江省最新疫情通報 11月26日0-24時,全省新增本土確診病例132例(含無癥狀感染者轉確診病例25例)。哈爾濱市85例(香坊區(qū)22例、南崗區(qū)17例、道里區(qū)17例、呼蘭區(qū)7例、…

                  2022年11月27日
                • 分享4條發(fā)微商朋友圈的方法(微商朋友圈應該怎么發(fā))

                  對于微商朋友來說,朋友圈的重要性不言而喻了。 那么微商的朋友圈到底該怎么發(fā)呢? 為什么同樣是經營一個朋友圈,有的微商看起來逼格滿滿,實際效果也不錯;而有的卻動都不動就被屏蔽甚至拉黑…

                  2022年11月27日
                • 短視頻策劃內容的3個要點(短視頻策劃內容怎么做)

                  短視頻在制作時,內容框架非常重要。如果直奔主題,然后結束,聚卓告訴你,這樣的短視頻已經過時了?,F在的短視頻需要框架的,但不是任何框架,它需要一種易于理解和消化的框架。而且,現在大多…

                  2022年11月27日
                • 存儲過程語法(sql server存儲過程語法)

                  今天小編給各位分享存儲過程語法的知識,其中也會對sql server存儲過程語法進行解釋,如果能碰巧解決你現在面臨的問題,別忘了關注本站,現在開始吧! oracle存儲過程基本語法…

                  2022年11月26日
                • 11月26日齊齊哈爾市疫情最新消息通報:昨日本土無癥狀感染者69例

                  11月25日0-24時,全省新增本土確診病例134例(含無癥狀感染者轉確診病例9例)。哈爾濱市117例(南崗區(qū)29例、香坊區(qū)28例、道里區(qū)22例、呼蘭區(qū)9例、道外區(qū)8例、松北區(qū)6例…

                  2022年11月26日
                • 11月26日黑河市疫情最新消息通報:昨日新增本土3+26

                  11月25日0-24時,全省新增本土確診病例134例(含無癥狀感染者轉確診病例9例)。哈爾濱市117例(南崗區(qū)29例、香坊區(qū)28例、道里區(qū)22例、呼蘭區(qū)9例、道外區(qū)8例、松北區(qū)6例…

                  2022年11月26日
                • 11月26日佳木斯市疫情最新消息通報:昨日新增本土5+14

                  11月25日0-24時,全省新增本土確診病例134例(含無癥狀感染者轉確診病例9例)。哈爾濱市117例(南崗區(qū)29例、香坊區(qū)28例、道里區(qū)22例、呼蘭區(qū)9例、道外區(qū)8例、松北區(qū)6例…

                  2022年11月26日
                • 11月26日綏化市疫情最新消息通報:昨日新增本土5+105

                  11月25日0-24時,全省新增本土確診病例134例(含無癥狀感染者轉確診病例9例)。哈爾濱市117例(南崗區(qū)29例、香坊區(qū)28例、道里區(qū)22例、呼蘭區(qū)9例、道外區(qū)8例、松北區(qū)6例…

                  2022年11月26日
                • 11月26日哈爾濱市疫情最新消息:昨日新增本土117+53

                  11月25日0-24時,全省新增本土確診病例134例(含無癥狀感染者轉確診病例9例)。哈爾濱市117例(南崗區(qū)29例、香坊區(qū)28例、道里區(qū)22例、呼蘭區(qū)9例、道外區(qū)8例、松北區(qū)6例…

                  2022年11月26日
                • 11月26日雙鴨山市疫情最新消息通報:昨日新增本土1+2

                  11月25日0-24時,全省新增本土確診病例134例(含無癥狀感染者轉確診病例9例)。哈爾濱市117例(南崗區(qū)29例、香坊區(qū)28例、道里區(qū)22例、呼蘭區(qū)9例、道外區(qū)8例、松北區(qū)6例…

                  2022年11月26日

                聯系我們

                聯系郵箱:admin#wlmqw.com
                工作時間:周一至周五,10:30-18:30,節(jié)假日休息