亚洲国产日韩人妖另类,久久只有这里有精品热久久,依依成人精品视频在线观看,免费国产午夜视频在线

      
      

        深入理解springboot的自動(dòng)注入

        深入理解springboot的自動(dòng)注入

        一、開(kāi)篇

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

        二、詳述

        2.1、什么是自動(dòng)注入

        ??天天將自動(dòng)注入,你真正明白自動(dòng)注入是怎么回事嗎?舉個(gè)例子來(lái)說(shuō),我們要在springboot中使用mybatis,之前的做法是什么?

        ??1、引入依賴(lài);

        ??2、在配置文件中配置配置類(lèi);

        ??3、寫(xiě)mybatis的配置文件或注解;

        ??在springboot中這個(gè)步驟就減少了,減少的是第二步,不用再寫(xiě)一堆配置類(lèi)了,步驟簡(jiǎn)化為:

        ??1、引入依賴(lài);

        ??2、寫(xiě)mybatis的配置文件或注解;

        ??也就是說(shuō)無(wú)需再搞配置類(lèi)了,就比如之前的”SqlSessionFactoryBean“,現(xiàn)在不用配置了,springboot為我們做了這些工作,現(xiàn)在看springboot引入mybatis需要加入的依賴(lài),

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

        ??我們加入mybatis和數(shù)據(jù)庫(kù)的驅(qū)動(dòng)依賴(lài),因?yàn)閙ybatis要使用數(shù)據(jù)庫(kù)連接,所以這里少不了mysql的數(shù)據(jù)庫(kù)驅(qū)動(dòng)。重點(diǎn)看mybatis的這個(gè)依賴(lài)和之前的是不一樣的,這個(gè)是”mybatis-spring-boot-starter“,再看這個(gè)依賴(lài)中都有哪些jar,

        ??除了常見(jiàn)的mybatis及mybatis-spring還有一個(gè)mybatis-spring-boot-autoconfigure,這個(gè)就是今天的主角。

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

        ??前邊說(shuō)到今天的主角是”mybatis-spring-boot-autoconfigure“,其實(shí)還有很多這樣的依賴(lài),大多數(shù)第三方自己實(shí)現(xiàn)的都會(huì)有這樣一個(gè)依賴(lài)比如,前邊自己實(shí)現(xiàn)的starter中就有這樣一個(gè)”customer-spring-boot-autoconfigurer“,還有很多都是springboot自己實(shí)現(xiàn)的,所以無(wú)需這樣的依賴(lài)。

        ??要想知道springboot是如何進(jìn)行自動(dòng)注入的,唯一的方式是debug,現(xiàn)在開(kāi)始debug之旅吧。

        2.2.1、SpringApplication構(gòu)造方法

        ??springboot的啟動(dòng)很簡(jiǎn)單,就是下面這樣一行代碼

        SpringApplication.run(BootServer.class);

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

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

        ??可以看的會(huì)new一個(gè)SpringApplication的實(shí)例,然后再調(diào)用其run方法,先看下new方法做了什么,最終調(diào)用的是下面的構(gòu)造方法,

        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(); //設(shè)置初始化器,很重要setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class)); //設(shè)置監(jiān)聽(tīng)器,很重要setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));this.mainApplicationClass = deduceMainApplicationClass();}

        ??我在上面 做了注釋?zhuān)攸c(diǎn)看注釋部分的代碼;

        2.2.2、setInitializers()方法

        ??該方法從方法名上看是要設(shè)置初始化器,其中g(shù)etSpringFactoriesInstances(ApplicationContextInitializer.class)是重點(diǎn)。其方法定義如下,

        private Collection getSpringFactoriesInstances(Class type, Class[] parameterTypes, Object… args) {ClassLoader classLoader = getClassLoader();// Use names and ensure unique to protect against duplicates //SpringFactoriesLoader.loadFactoryNames是重點(diǎn)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)方法是重點(diǎn)return loadSpringFactories(classLoader).getOrDefault(factoryTypeName, Collections.emptyList());}

        ??把斷點(diǎn)放在loadSpringFactroies方法內(nèi),

        ??從上面的debug結(jié)果可以看到使用AppClassLoader讀取”FACTORIES_RESOURCE_LOCATION“處的資源,AppClassLoader大家都很熟悉,就說(shuō)應(yīng)用類(lèi)加載器,常量”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“文件,也就是說(shuō)要讀取項(xiàng)目中jar包中的”META-INF/spring.factories“文件的內(nèi)容,我在spring-boot-2.3.3.RELEASE.jar中找到這樣一個(gè)文件,僅截個(gè)圖,詳細(xì)內(nèi)容可以自己查看,

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

        ??這個(gè)返回值是,項(xiàng)目中所有jar下META-INF/spring.factories文件中的鍵值對(duì)組成的map?;氐絣oadFactoryNames方法處

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

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

        2.2.3、setListeners()方法

        ??該方法和setInitializers方法是類(lèi)似的,

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

        ??本人核實(shí)過(guò)這些的確是從spring.factories文件中讀取的,和其內(nèi)容是一致的。

        寫(xiě)到這里其實(shí)和自動(dòng)注入沒(méi)有關(guān)系,如果說(shuō)有關(guān)系的話(huà)是,這里認(rèn)識(shí)了一個(gè)關(guān)鍵的類(lèi)”SpringFactoriesLoader“,該類(lèi)的作用就是讀取jar包中META-INF/spring.facotries文件的內(nèi)容。在后邊的自動(dòng)注入中還會(huì)出現(xiàn)該類(lèi)的影子。繼續(xù)向前。

        2.3、自動(dòng)注入的原理

        2.3.1、@SpringBootApplication注解??

        在啟動(dòng)springboot程序的時(shí)候在程序的入口都會(huì)有寫(xiě)上@SpringBootApplication的注解,

        package com.my.template;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;/** * 啟動(dòng)類(lèi) * @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三個(gè)注解,今天重點(diǎn)看@EnableAutoConfiguration注解。

        2.3.2、@EnableAutoConfiguration注解

        ??該注解便是自動(dòng)注入的核心注解,

        ??重點(diǎn)是該注解上的下面這句話(huà),

        @Import(AutoConfigurationImportSelector.class)

        ??看下AutoConfigurationImportSelector類(lèi),該類(lèi)中有這樣一個(gè)方法,和自動(dòng)注入是相關(guān)的,

        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類(lèi)又出現(xiàn)了,還是很熟悉的loadFactoryNames方法,這次的方法參數(shù)是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的。

        也就是說(shuō)要把這些配置類(lèi)加到spring的容器中。現(xiàn)在有個(gè)問(wèn)題這些配置都會(huì)生效嗎?

        2.3.3、這些配置類(lèi)都會(huì)生效嗎?

        ??上面說(shuō)到自動(dòng)配置會(huì)加載很多的配置類(lèi),但是這些類(lèi)都會(huì)生效嗎?答案是不會(huì)的,只會(huì)在特定情況下生效,以MybatisAutoConfiguration為例,

        ??可以看的該類(lèi)上有很多注解,

        ??@ConditionalOnClass,當(dāng)類(lèi)路徑中存在某個(gè)類(lèi)標(biāo)識(shí)該注解的類(lèi)才會(huì)生效,也就是只有存在SqlSessionFactory、SqlSessionFactoryBean才會(huì)解析MybatisAutoConfiguration類(lèi)。換句話(huà)說(shuō),要有mybatis、mybatis-spring的jar包。

        ??@ConditionaleOnSigleCanidate,需要一個(gè)單例bean

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

        ??@AutoConfigureAfter 自動(dòng)配置在某個(gè)類(lèi)之后

        現(xiàn)在我們知道了一個(gè)XXAutoConfiguration類(lèi)是否會(huì)生效還要看其上面的注解是怎么定義的。

        三、總結(jié)

        ??本文主要分析了springboot的自動(dòng)注入原理,

        ??1、注解@SpringBootApplication中含有三個(gè)注解,其中@EnabelAutoConfiguration和自動(dòng)配置有關(guān);

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

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

        鄭重聲明:本文內(nèi)容及圖片均整理自互聯(lián)網(wǎng),不代表本站立場(chǎng),版權(quán)歸原作者所有,如有侵權(quán)請(qǐng)聯(lián)系管理員(admin#wlmqw.com)刪除。
        上一篇 2022年6月27日 06:22
        下一篇 2022年6月27日 06:23

        相關(guān)推薦

        聯(lián)系我們

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