最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Springboot Spring原理2深度解析

 更新時間:2025年11月29日 09:42:39   作者:曾經的三心草  
SpringBoot的?動配置就是當Spring容器啟動后, ?些配置類, bean對象等就自動存入到了IoC容器中,不需要我們手動去聲明, 從而簡化了開發(fā), 省去了繁瑣的配置操作,這篇文章介紹Springboot Spring原理2,感興趣的朋友一起看看吧

提示:文章寫完后,目錄可以自動生成,如何生成可參考右邊的幫助文檔

前言

3. Spring Boot?動配置

自動裝配是屬性的自動裝配,比如剛剛說的,set注入ben,構造方法注入bean
自動配置呢

SpringBoot的?動配置就是當Spring容器啟動后, ?些配置類, bean對象等就自動存入到了IoC容器中,不需要我們手動去聲明, 從而簡化了開發(fā), 省去了繁瑣的配置操作.
SpringBoot?動配置, 就是指SpringBoot是如何將依賴jar包中的配置類以及Bean加載到Spring IoC容
器中的.
主要分以下兩個??:

  1. Spring 是如何把對象加載到SpringIoC容器中的
  2. SpringBoot 是如何實現的

3.1 Spring 加載Bean

為什么加入依賴,一些bean,注解(@Mapper),就自動配置了

比如我們現在加入了一個包autoconfig,假設它是第三方的包
如果對這個打包,通過pom引入,那么就會出現在外部庫中

所以這個我們自定義的第三方的包,放在這里和放在外部庫是一樣的效果
為什么放在這里效果和打包加依賴放在外部庫是一樣的效果呢
因為啟動類只能加載它所在目錄下的所有bean,不能加載它所在目錄下的其他包下的bean的
我們的包autoconfig就是放在外面的

@Component
public class CkConfig {
    public void use(){
        System.out.println("CkConfig");
    }
}

然后我們在項目中就想使用這個包

@SpringBootApplication
public class SpringPrinciple2Application {
    public static void main(String[] args) {
        ApplicationContext context = SpringApplication.run(SpringPrinciple2Application.class, args);
        CkConfig bean = context.getBean(CkConfig.class);
        bean.use();
    }
}

執(zhí)行

直接報錯了,說找不到這個bean

因為spring掃描的路徑,默認是啟動類所在的目錄
但是這個包在外面,所有加了注解Component也沒有用

第一種方式是使用注解ComponentScan,這個就是指定要掃描的路徑了

@SpringBootApplication
@ComponentScan("com.ck.demo.autoconfig")
public class SpringPrinciple2Application {

    public static void main(String[] args) {
        ApplicationContext context = SpringApplication.run(SpringPrinciple2Application.class, args);
        CkConfig bean = context.getBean(CkConfig.class);
        bean.use();
    }

}

這樣就成功了

就是手動指定spring的掃描路徑,但是缺點就是所有的外部的bean都要手動指定,比如redis的,mybatis的包都要手動加入

而且加了ComponentScan的話,原來的啟動類下的路徑就不會再掃描了,意思就是原來的config下的bean,就是package com.ck.demo.springprinciple2;包下的都不會再掃描了

ComponentScan下可以寫數組的

@SpringBootApplication
@ComponentScan({"com.ck.demo.autoconfig","com.ck.demo.springprinciple2"})
public class SpringPrinciple2Application {
    public static void main(String[] args) {
        ApplicationContext context = SpringApplication.run(SpringPrinciple2Application.class, args);
        CkConfig bean = context.getBean(CkConfig.class);
        bean.use();
    }
}

所以這樣之前的,和新加入的都可以生效了

@Import(CkConfig.class)
@SpringBootApplication
public class SpringPrinciple2Application {
    public static void main(String[] args) {
        ApplicationContext context = SpringApplication.run(SpringPrinciple2Application.class, args);
        CkConfig bean = context.getBean(CkConfig.class);
        bean.use();
    }
}

還可以通過這個方式,使用注解Import,來導入class

但是spring的話,這兩種方式都沒有采用

@Import({CkConfig.class, CkConfig2.class})

也是可以添加多個的

public class MyImport implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"com.ck.demo.autoconfig.CkConfig","com.ck.demo.autoconfig.CkConfig2"};
    }
}

我們在第三方autoconfig下寫一個這個類,表示Import要掃描的路徑

@Import(MyImport.class)
@SpringBootApplication
public class SpringPrinciple2Application {
    public static void main(String[] args) {
        ApplicationContext context = SpringApplication.run(SpringPrinciple2Application.class, args);
        CkConfig bean = context.getBean(CkConfig.class);
        bean.use();
    }
}

這樣就可以了,這個就是第三方提供給你bean的路徑

但是還是麻煩,繼續(xù)升級,第三方提供注解就好了

@Target(ElementType.TYPE)//這個注解可以加在什么地方上
@Retention(RetentionPolicy.RUNTIME)//生命周期
@Import(MyImport.class)//注解的作用
public @interface EnableCkConfig {
}

這個注解定義在autoconfig下,也是第三方提供的

@EnableCkConfig
@SpringBootApplication
public class SpringPrinciple2Application {
    public static void main(String[] args) {
        ApplicationContext context = SpringApplication.run(SpringPrinciple2Application.class, args);
        CkConfig bean = context.getBean(CkConfig.class);
        bean.use();
        CkConfig2 bean2 = context.getBean(CkConfig2.class);
        bean2.use();
    }
}

這樣就可以了

所以第三方只需要提供注解就可以了

但是導入mybatis的依賴的時候,就那些bean也不用在啟動類上加入注解啊
所以還有其他方式,連注解也不需要加
就是在resource目錄下創(chuàng)建一個文件,放入"com.ck.demo.autoconfig.CkConfig","com.ck.demo.autoconfig.CkConfig2"這些東西,就會自動創(chuàng)建和管理了

這個文件就是META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
放入

com.ck.demo.autoconfig.CkConfig
com.ck.demo.autoconfig.CkConfig2

這個就是告訴spring,我要管理哪些對象

這樣的話,自定義注解EnableCkConfig也不需要了,也可以獲取第三方的bean了

3.2 源碼分析

但是spring用的是什么方式呢
我們去看啟動類@SpringBootApplication
因為這個注解,所以它是啟動類
還有ApplicationContext context = SpringApplication.run(SpringPrinciple2Application.class, args);這個來啟動

點進去注解SpringBootApplication

@Target({ElementType.TYPE})表示主要要加在什么上

@Retention(RetentionPolicy.RUNTIME)生命周期

@Documented文檔相關

@Inherited繼承相關,是源注解,不看了

@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan

這三個最重要

@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)

因為這個,所以會掃碼啟動類下的路徑
加了這個,默認掃描ComponentScan注解所在的路徑,也就是SpringBootApplication注解所在的路徑

SpringBootConfiguration注解點進去

Indexed注解是一個優(yōu)化的注解,不重要

重點是Configuration,五大注解之一,所以SpringBootConfiguration注解就是Configuration分裝了一下
所以注解SpringBootConfiguration表示這是一個配置類,這個會被spring給識別到

所以重點就是注解EnableAutoConfiguration了

3.3 注解@EnableAutoConfiguration

@Import({AutoConfigurationImportSelector.class})

AutoConfigurationImportSelector這個實現了DeferredImportSelector,DeferredImportSelector實現了ImportSelector

實現了方法selectImports
返回了要管理的bean

            AutoConfigurationEntry autoConfigurationEntry = this.getAutoConfigurationEntry(annotationMetadata);
            return StringUtils.toStringArray(autoConfigurationEntry.getConfigurations());

主要是從這個getAutoConfigurationEntry來的
點進去

AnnotationMetadata是注解的原信息

List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);

這個方法點進去

這個就是加載配置了
Assert是斷言

        String aa=null;
        Assert.notNull(aa,"aa不能為空");

比如這個意思就是斷言aa不能為空
為空的話,就報"aa不能為空"的錯誤

這個斷言的就是沒有配置信息在META-INF/spring/。。。。。
所以

 ImportCandidates importCandidates = ImportCandidates.load(this.autoConfigurationAnnotation, this.getBeanClassLoader());

這個就是讀取META-INF/spring/這個文件的配置信息的,沒有的話,就會包一個異常

但是我們平時并沒有這個文件啊,為什么沒有報錯

ctrl+N搜索org.springframework.boot.autoconfigure.AutoConfiguration.imports

點擊第一個

找到這里,發(fā)現這里就有那個META-INF/spring/的文件

這里面放的就是spring要加載的bean
說明spring它自己就寫了一個這種文件了
所以要管理我們第三方的bean的話,也是寫一個這個路徑就可以了,spring就會認識了,spring是根據路徑來掃描的,都是這個路徑的就都可以掃描到了

比如這個里面就有事務
spring就會管理DataSourceTransactionManagerAutoConfiguration這個bean了
ctrl+n搜索

然后DataSourceTransactionManagerAutoConfiguration這個里面還有bean
這樣就都生效了

比如redis的,搜索RedisAutoConfiguration這個bean

然后RedisAutoConfiguration這個bean里面就有RedisTemplate這個bean,所以RedisTemplate這個bean也是自動注入的

除了@Bean之外,還有其他注解

比如注解ConditionalOnMissingBean
表示在不同的條件下才注入這個bean

@Bean
@ConditionalOnMissingBean
    public StringRedisTemplate stringRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
        return new StringRedisTemplate(redisConnectionFactory);
    }

這個意思就是,如果你沒有聲明stringRedisTemplate這個Bean,我就聲明stringRedisTemplate這個bean

    @ConditionalOnMissingBean(
        name = {"redisTemplate"}
    )

意思就是你要是聲明了redisTemplate這個bean,我就不聲明了,你沒有聲明,我就聲明

@ConditionalOnClass({RedisOperations.class})

看有沒有RedisOperations這個類,沒有的話,這個類下的所有bean都不,包括自己這個類的bean都不生效

這個RedisOperations就在import org.springframework.data.redis.core.RedisOperations;上面擺著
這個RedisOperations類就是我們要引入的依賴里面的,換個意思就是沒有引入依賴,就沒有RedisOperations這個類,就不能加載Bean了

所以加了依賴,外部庫就有org.springframework.data.redis.core,這個類RedisOperations就有了,對應的RedisAutoConfiguration和它下面的方法這些Bean就有了

不加依賴所以就不行了

繼續(xù)回到這里,就是獲取META-INF/spring/配置的這里
就是

List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);

這里configurations就是META-INF/spring/文件里面的配置,包括我們自己寫在META-INF/spring/里面的

this.checkExcludedClasses(configurations, exclusions);

這個是檢查排除,根據依賴信息來檢查排除

 configurations.removeAll(exclusions);

這個就是刪除沒有引入依賴的配置

最后返回

所以getAutoConfigurationEntry返回的就是要求spring給我們管理的配置,對象,bean

所以注解@Import({AutoConfigurationImportSelector.class}),返回的就是要求spring給我們管理的配置,對象,bean

現在我們看AutoConfigurationPackage這個注解

它又import了

import了Register,這又是一個我們注入包的方式

Register加載bean

public class MyRegister implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
        beanDefinition.setBeanClass(CkConfig.class);
//        beanDefinition.setScope("xxxx");//表示這個bean是單例的還是多例的
        registry.registerBeanDefinition("ckConfig",beanDefinition);//注入bean,第一個參數是bean的名稱
    }
}

我們在autoconfig下定義MyRegister

@SpringBootApplication
@Import(MyRegister.class)
public class SpringPrinciple2Application {
    public static void main(String[] args) {
        ApplicationContext context = SpringApplication.run(SpringPrinciple2Application.class, args);
        CkConfig bean = context.getBean(CkConfig.class);
        bean.use();
//        CkConfig2 bean2 = context.getBean(CkConfig2.class);
//        bean2.use();
    }
}

這又是一種方式導入在這里插入代碼片

繼續(xù)分析

這里定義了一個Register的類
定義了registerBeanDefinitions這個方法

        public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
            AutoConfigurationPackages.register(registry, (String[])(new PackageImports(metadata)).getPackageNames().toArray(new String[0]));
        }

(String[])(new PackageImports(metadata)).getPackageNames().toArray(new String[0])這個得到的就是我們啟動類所在路徑com.ck.demo.springprinciple2

AutoConfigurationPackages.register這個就是注入第三方的注解,比如@Mapper

為什么spring能夠管理第三方的注解

第三方就會寫那些register
然后給我們注入

然后BlogInfoMapper使用了注解Mapper
然后注解Mapper就會拿到BlogInfoMapper的路徑

比如我們搜索這個MybatisPlus的這個類

找到這里,這里實現了Register

這里調用的registerBeanDefinitions,就是我們剛剛看到的啟動類原碼里面定義的方法

就是這個方法

這里會得到啟動類的路徑
然后在這個啟動類里面掃描得到Mapper注解,掃描誰加了Mapper注解
然后調用方法registerBeanDefinitions加到spring就可以管理了
這個就是MybatisPlus第三方注解加入Bean的方式

就是調用第三方的注解,但是第三方的注解不是立馬加入Bean,而是,先獲取啟動類路徑,根據啟動類路徑掃描誰
調用了Mapper注解,誰調用個,就調用方法registerBeanDefinitions加到spring就可以管理了

public class MyRegister implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
        beanDefinition.setBeanClass(CkConfig.class);
//        beanDefinition.setScope("xxxx");//表示這個bean是單例的還是多例的
        registry.registerBeanDefinition("ckConfig",beanDefinition);//注入bean,第一個參數是bean的名稱
    }
}

比如這個,xx使用了注解Mapper(會自動調用相應方法),—》把xx給registry.registerBeanDefinition,然后MyRegister 由于引入了依賴,而且implements ImportBeanDefinitionRegistrar,就自動會被spring給@Import(MyRegister.class)

3.4 總結

AutoConfigurationPackage用的是Register的方式來注入bean,主要是用來掃描第三方注解,比如@Mapper,
第三方實現ImportBeanDefinitionRegistrar,然后就可以注入了

當SpringBoot程序啟動時, 會加載配置?件當中所定義的配置類, 通過 @Import 注解將這些配置類全
部加載到Spring的IOC容器中, 交給IOC容器管理.

  1. Bean的作?域共分為6種: singleton, prototype, request, session, application和websocket.
  2. Bean的?命周期共分為5?部分: 實例化, 屬性復制, 初始化, 使?和銷毀
  3. SpringBoot的?動配置原理源碼?是 @SpringBootApplication 注解, 這個注解封裝了3個注解?@SpringBootConfiguration 標志當前類為配置類
    ? @ComponentScan 進?包掃描(默認掃描的是啟動類所在的當前包及其?包)
    ? @EnableAutoConfiguration
    ? @Import 注解 : 讀取當前項?下所有依賴jar包中 META-INF/spring.factories ,
    METAINF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 兩個?件??定義的配置類(配置類中定義了 @Bean 注解標識的?法)
    ? @AutoConfigurationPackage : 把啟動類所在的包下?所有的組件都注?到 Spring容器中

總結

到此這篇關于Springboot Spring原理2的文章就介紹到這了,更多相關Springboot Spring原理內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Spring中的@Value和@PropertySource注解詳解

    Spring中的@Value和@PropertySource注解詳解

    這篇文章主要介紹了Spring中的@Value和@PropertySource注解詳解,@PropertySource:讀取外部配置文件中的key-value保存到運行的環(huán)境變量中,本文提供了部分實現代碼,需要的朋友可以參考下
    2023-11-11
  • 多個版本Java切換環(huán)境變量配置的三種高效方法

    多個版本Java切換環(huán)境變量配置的三種高效方法

    這篇文章主要為大家詳細介紹了多個版本Java切換環(huán)境變量配置的三種高效方法,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下
    2025-10-10
  • WebSocket實現數據庫更新時前端頁面刷新

    WebSocket實現數據庫更新時前端頁面刷新

    這篇文章主要為大家詳細介紹了WebSocket實現數據庫更新時前端頁面刷新,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-04-04
  • SpringCloud使用Nacos作為配置中心統(tǒng)一管理配置方式

    SpringCloud使用Nacos作為配置中心統(tǒng)一管理配置方式

    文章介紹了如何引入依賴、創(chuàng)建bootstrap.properties文件、添加配置信息、使用注解動態(tài)獲取及刷新配置等步驟,以便優(yōu)先從Nacos中獲取配置信息
    2026-05-05
  • Java中Singleton的3種實現方式詳解

    Java中Singleton的3種實現方式詳解

    這篇文章主要給大家介紹了關于Java中Singleton的3種實現方式,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-02-02
  • java如何獲取用戶登錄ip、瀏覽器信息、SessionId

    java如何獲取用戶登錄ip、瀏覽器信息、SessionId

    這篇文章主要介紹了java如何獲取用戶登錄ip、瀏覽器信息、SessionId,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Springboot+QueryDsl實現融合數據查詢

    Springboot+QueryDsl實現融合數據查詢

    這篇文章主要將介紹的是 Springboot 使用 QueryDsl 實現融合數據查詢,文中有詳細的代碼講解,對 SpringBoot?Querydsl?查詢操作感興趣的朋友一起看看吧
    2023-08-08
  • MyBatis中高級多表查詢(ResultMap、association、collection)詳解

    MyBatis中高級多表查詢(ResultMap、association、collection)詳解

    文章主要介紹了MyBatis中高級多表查詢的四種方式:ResultMap、association、collection以及自連接查詢,通過定義接口的抽象方法、編寫mapper.xml和測試類,詳細展示了如何根據復雜數據結構進行數據的裝配和查詢,感興趣的朋友一起看看吧
    2024-11-11
  • Java日常練習題,每天進步一點點(34)

    Java日常練習題,每天進步一點點(34)

    下面小編就為大家?guī)硪黄狫ava基礎的幾道練習題(分享)。小編覺得挺不錯的,現在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧,希望可以幫到你
    2021-07-07
  • Java發(fā)送報文與接收報文的實例代碼

    Java發(fā)送報文與接收報文的實例代碼

    這篇文章主要介紹了Java發(fā)送報文與接收報文,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-03-03

最新評論

邯郸市| 沙河市| 桂东县| 石河子市| 成武县| 卓资县| 松潘县| 塔河县| 洪洞县| 喜德县| 墨竹工卡县| 邯郸县| 新营市| 河北区| 商丘市| 嘉兴市| 左贡县| 中西区| 文成县| 汉寿县| 虞城县| 临城县| 中卫市| 固安县| 库尔勒市| 岢岚县| 自治县| 琼结县| 合川市| 响水县| 曲沃县| 潞西市| 泰兴市| 县级市| 宁化县| 涞源县| 博客| 江北区| 布尔津县| 武胜县| 巴彦县|