SpringBoot自動(dòng)裝配

一、前世今生

在弄清楚為什么有自動(dòng)裝配這個(gè)概念前,不妨讓我們回顧下,作為JAVA后端程序員,我們歷史上是怎么做的。

  • spring 配置大量的xml,形如如下的配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">
    <bean id="moocAppctx" class="imooc_spring.test.aware.MoocApplicationContext"
        init-method="hhhh">
    </bean>
</beans>
  • spring boot時(shí)代,你會(huì)驚奇的發(fā)現(xiàn),這些配置文件都不存在了。但來(lái)的是你加了些基礎(chǔ)依賴后,直接啟動(dòng)部分調(diào)用如下代碼后,整個(gè)spring就起飛了。
@SpringBootApplication(scanBasePackages = {"com.bianque.dqc"})
@MapperScan(basePackages = "com.test.mybatis.mapper", annotationClass = Mapper.class)
public class TestApplication {
    public static void main(String[] args) {
        SpringApplication.run(DqcApplication.class, args);
    }
}

作為對(duì)springboot不熟悉的你,會(huì)比較疑惑,為什么會(huì)有這種情況出現(xiàn),是不是

  • spring boot重復(fù)造了套輪子,沒(méi)有在使用這套xml技術(shù)了。
  • spring boot使用了牛逼的技術(shù),跳出三界之外了。

帶著這樣的疑惑,我們發(fā)現(xiàn)spring boot的開(kāi)發(fā)與以往的spring開(kāi)發(fā)相比,優(yōu)勢(shì)就是只需要很少的代碼,就可以實(shí)現(xiàn)基礎(chǔ)的功能,也就是大家常說(shuō)的開(kāi)箱即用。哪么為什么能這么簡(jiǎn)單呢。

答案就是今天的主角:<b>自動(dòng)裝配</b>。
總結(jié)一句話:自動(dòng)裝配技術(shù),使得我們?cè)谑褂胹pringboot框架時(shí),通過(guò)以往積累的經(jīng)驗(yàn),針對(duì)大部分的配置采用默認(rèn)化,從大量重復(fù)的勞動(dòng)中解放出來(lái),專注業(yè)務(wù)本身。
這里可能有同學(xué)會(huì)問(wèn),沒(méi)有SpringBoot的前提下,我們可以完成Spring程序開(kāi)發(fā)嘛,答案是一定可以,只是技術(shù)的進(jìn)步是解放生產(chǎn)力,由于SpringBoot。解放了大量的配置勞動(dòng)。此時(shí)生產(chǎn)力自然提升。

二、抽絲剝繭

在理解了為什么SpringBoot出現(xiàn)的背景后,接下來(lái),我們要核心的講解下,他是怎么實(shí)現(xiàn)的自動(dòng)裝配。學(xué)習(xí)理解框架,最直接的版本,就是讀源碼。所以接下來(lái),我們會(huì)以一個(gè)實(shí)際的測(cè)試工程的源碼開(kāi)始,來(lái)一層層抽絲剝繭的系統(tǒng)講解,自動(dòng)裝配的實(shí)現(xiàn)邏輯。

1. @SpringBootApplication

在很多源碼剖析的書(shū)中或者文章中,都開(kāi)篇來(lái)將這個(gè)注解。我們也不能免俗,大家通過(guò)idea新建一工程后,首先看到的代碼大概如下所示:

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {

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

點(diǎn)擊到SpringBootApplication內(nèi)部,我們發(fā)現(xiàn)最核心的就

  • @SpringBootConfiguration
  • @EnableAutoConfiguration
  • @ComponentScan
    核心就看EnableAutoConfiguration

2. @EnableAutoConfiguration

定義如下:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
    String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";

    Class<?>[] exclude() default {};

    String[] excludeName() default {};
}

三、返璞歸真

SpringBoot所有自動(dòng)配置類都是在啟動(dòng)的時(shí)候進(jìn)行掃描并加載,通過(guò)spring.factories可以找到自動(dòng)配置類的路徑,但是不是所有存在于spring,factories中的配置都進(jìn)行加載,而是通過(guò)@ConditionalOnClass注解進(jìn)行判斷條件是否成立(只要導(dǎo)入相應(yīng)的stater,條件就能成立),如果條件成立則加載配置類,否則不加載該配置類。

總結(jié)如下

1.通過(guò)各種注解實(shí)現(xiàn)了類與類之間的依賴關(guān)系,容器在啟動(dòng)的時(shí)候Application.run,會(huì)調(diào)用EnableAutoConfigurationImportSelector.class的selectImports方法(其實(shí)是其父類的方法)--這里需要注意,調(diào)用這個(gè)方法之前發(fā)生了什么和是在哪里調(diào)用這個(gè)方法需要進(jìn)一步的探討

2.selectImports方法最終會(huì)調(diào)用SpringFactoriesLoader.loadFactoryNames方法來(lái)獲取一個(gè)全面的常用BeanConfiguration列表

3.loadFactoryNames方法會(huì)讀取FACTORIES_RESOURCE_LOCATION(也就是spring-boot-autoconfigure.jar 下面的spring.factories),獲取到所有的Spring相關(guān)的Bean的全限定名ClassName,大概120多個(gè)

4.selectImports方法繼續(xù)調(diào)用filter(configurations, autoConfigurationMetadata);這個(gè)時(shí)候會(huì)根據(jù)這些BeanConfiguration里面的條件,來(lái)一一篩選,最關(guān)鍵的是
@ConditionalOnClass,這個(gè)條件注解會(huì)去classpath下查找,jar包里面是否有這個(gè)條件依賴類,所以必須有了相應(yīng)的jar包,才有這些依賴類,才會(huì)生成IOC環(huán)境需要的一些默認(rèn)配置Bean

5.最后把符合條件的BeanConfiguration注入默認(rèn)的EnableConfigurationPropertie類里面的屬性值,并且注入到IOC環(huán)境當(dāng)中

參考文檔:http://www.itdecent.cn/p/88eafeb3f351

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容