0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

初學(xué)者必看的SpringBoo自動裝配原理1

jf_78858299 ? 來源:CSDN ? 作者:CC_且聽風(fēng)吟 ? 2023-04-07 11:03 ? 次閱讀

前言

學(xué)習(xí)SpringBoot,絕對避不開自動裝配這個概念,這也是SpringBoot的關(guān)鍵之一

本人也是SpringBoot的初學(xué)者,下面的一些總結(jié)都是結(jié)合個人理解和實踐得出的,如果有錯誤或者疏漏,請一定一定一定(不是歡迎,是一定)幫我指出,在評論區(qū)回復(fù)即可,一起學(xué)習(xí)!

篇幅較長分四篇了,希望你可以有耐心.

如果只關(guān)心SpringBoot裝配過程,可以直接跳到第7部分

想要理解spring自動裝配,需要明確兩個含義:

  • 裝配,裝配什么?
  • 自動,怎么自動?

1. Warm up

在開始之前,讓我們先來看點簡單的開胃菜:spring中bean注入的三種形式

首先我們先來一個Person類,這里為了篇幅長度考慮使用了lombok

如果你不知道lombok是什么,那就最好不要知道,加了幾個注解之后我的pojo類Person就完成了

/**
 * @author dzzhyk
 */
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Person {
    private String name;
    private Integer age;
    private Boolean sex;
}

在Spring中(不是Spring Boot),要實現(xiàn)bean的注入,我們有3種注入方式:

1.1 setter注入

這是最基本的注入方式

首先我們創(chuàng)建applicationContext.xml文件,在里面加入:

<bean id="person" class="pojo.Person">
    <property name="name" value="dzzhyk"/>
    <property name="age" value="20"/>
    <property name="sex" value="true"/>
<span class="hljs-name"bean>

這里使用property為bean對象賦值

緊接著我們會在test包下寫一個version1.TestVersion1類

/**
 * 第一種bean注入實現(xiàn)方式 - 在xml文件中直接配置屬性
 */
public class TestVersion1 {
    @Test
    public void test(){
        ApplicationContext ca = new   ClassPathXmlApplicationContext("applicationContext.xml");
        Person person = ca.getBean("person", Person.class);
        System.out.println(person);
    }
}

這里我使用了ClassPathXmlApplicationContext來加載spring配置文件并且讀取其中定義的bean,然后使用getBean方法使用id和類來獲取這個Person的Bean對象,結(jié)果成功輸出:

Person(name=dzzhyk, age=20, sex=true)

1.2 構(gòu)造器注入

接下來是使用構(gòu)造器注入,我們需要更改applicationContext.xml文件中的property為construct-arg

class="pojo.Person">
    index="0" type="java.lang.String" value="dzzhyk" />
    index="1" type="java.lang.Integer" value="20"/>
    index="2" type="java.lang.Boolean" value="true"/>
class="hljs-name"bean>

version2.TestVersion2內(nèi)容不變:

public class TestVersion2 {
    @Test
    public void test(){
        ApplicationContext ca = new ClassPathXmlApplicationContext("applicationContext.xml");
        Person person = ca.getBean("person", Person.class);
        System.out.println(person);
    }
}

依然正常輸出結(jié)果:

Person(name=dzzhyk, age=20, sex=true)

1.3 屬性注入

使用注解方式的屬性注入Bean是比較優(yōu)雅的做法

首先我們需要在applicationContext.xml中開啟注解支持和自動包掃描:

<context:annotation-config />
<context:component-scan base-package="pojo"/>

在pojo類中對Person類加上@Component注解,將其標(biāo)記為組件,并且使用@Value注解為各屬性賦初值

@Component
public class Person {
    
    @Value("dzzhyk")
    private String name;
    @Value("20")
    private Integer age;
    @Value("true")
    private Boolean sex;
}

然后添加新的測試類version3.TestVersion3

public class TestVersion3 {
    @Test
    public void test(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        Person person = ac.getBean("person", Person.class);
        System.out.println(person);
    }
}

運行也可以得到如下結(jié)果:

Person(name=dzzhyk, age=20, sex=true)

2. Warm up again

什么?還有什么?接下來我們來聊聊Spring的兩種配置方式:基于XML的配置和基于JavaConfig類的配置方式,這對于理解SpringBoot的自動裝配原理是非常重要的。

首先我們在Person的基礎(chǔ)上再創(chuàng)建幾個pojo類:這個Person有Car、有Dog

public class Car {
    private String brand;
    private Integer price;
}

public class Dog {
    private String name;
    private Integer age;
}

public class Person {
    private String name;
    private Integer age;
    private Boolean sex;
    private Dog dog;
    private Car car;
}

2.1 基于XML的配置

接下來讓我們嘗試使用XML的配置方式來為一個Person注入

class="pojo.Person">
    name="name" value="dzzhyk"/>
    name="age" value="20"/>
    name="sex" value="true"/>
    name="dog" ref="dog"/>
    name="car" ref="car"/>
class="hljs-name"bean>

class="pojo.Dog">
    name="name" value="旺財"/>
    name="age" value="5" />
class="hljs-name"bean>

class="pojo.Car">
    name="brand" value="奧迪雙鉆"/>
    name="price" value="100000"/>
class="hljs-name"bean>

然后跟普通的Bean注入一樣,使用ClassPathXmlApplicationContext來加載配置文件,然后獲取Bean

/**
 * 使用XML配置
 */
public class TestVersion1 {
    @Test
    public void test(){
        ClassPathXmlApplicationContext ca = new ClassPathXmlApplicationContext("applicationContext.xml");
        Person person = ca.getBean("person", Person.class);
        System.out.println(person);
    }
}

輸出結(jié)果如下:

Person(name=dzzhyk, age=20, sex=true, dog=Dog(name=旺財, age=5), car=Car(brand=奧迪雙鉆, price=100000))

2.2 基于JavaConfig類的配置

想要成為JavaConfig類,需要使用@Configuration注解

我們新建一個包命名為config,在config中新增一個PersonConfig類

@Configuration
@ComponentScan
public class PersonConfig {

    @Bean
    public Person person(Dog dog, Car car){
        return new Person("dzzhyk", 20, true, dog, car);
    }

    @Bean
    public Dog dog(){
        return new Dog("旺財", 5);
    }

    @Bean
    public Car car(){
        return new Car("奧迪雙鉆", 100000);
    }
}

此時我們的XML配置文件可以完全為空了,此時應(yīng)該使用AnnotationConfigApplicationContext來獲取注解配置

/**
 * 使用JavaConfig配置
 */
public class TestVersion2 {
    @Test
    public void test(){
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(PersonConfig.class);
        Person person = ac.getBean("person", Person.class);
        System.out.println(person);
    }
}

仍然正常輸出了結(jié)果:

Person(name=dzzhyk, age=20, sex=true, dog=Dog(name=旺財, age=5), car=Car(brand=奧迪雙鉆, price=100000))

3. BeanDefinition

AbstractBeanDefinition

是spring中所有bean的抽象定義對象,我把他叫做bean定義

當(dāng)bean.class被JVM類加載到內(nèi)存中時,會被spring掃描到一個map容器中:

BeanDefinitionMap

這個容器存儲了bean定義,但是bean此時還沒有進(jìn)行實例化,在進(jìn)行實例化之前,還有一個

BeanFactoryPostProcessor

可以對bean對象進(jìn)行一些自定義處理

我們打開BeanFactoryProcessor這個接口的源碼可以發(fā)現(xiàn)如下內(nèi)容:

/*
* Modify the application context's internal bean factory after its standard
* initialization. All bean definitions will have been loaded, but no beans
* will have been instantiated yet. This allows for overriding or adding
* properties even to eager-initializing beans.
*/

在spring完成標(biāo)準(zhǔn)的初始化過程后,實現(xiàn)BeanFactoryPostProcessor接口的對象可以用于定制bean factory,所有的bean definition都會被加載,但是此時還沒有被實例化。這個接口允許對一些bean定義做出屬性上的改動。

簡言之就是實現(xiàn)了BeanFactoryPostProcessor這個接口的類,可以在bean實例化之前完成一些對bean的改動。

大致流程我畫了個圖:

至此我們能總結(jié)出springIOC容器的本質(zhì):(我的理解)

由BeanDefinitionMap、BeanFactoryPostProcessor、BeanPostProcessor、BeanMap等等容器共同組成、共同完成、提供依賴注入和控制反轉(zhuǎn)功能的一組集合,叫IOC容器。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • spring
    +關(guān)注

    關(guān)注

    0

    文章

    335

    瀏覽量

    14278
  • 源碼分析
    +關(guān)注

    關(guān)注

    0

    文章

    5

    瀏覽量

    5537
  • 自動裝配
    +關(guān)注

    關(guān)注

    0

    文章

    7

    瀏覽量

    641
收藏 人收藏

    評論

    相關(guān)推薦

    protel技術(shù)大全--初學(xué)者必看

    protel技術(shù)大全--初學(xué)者必看。
    發(fā)表于 08-04 10:36

    PSOC1初學(xué)者必看的10個實例

    PSOC1初學(xué)者必看的10個實例
    發(fā)表于 11-19 16:33

    MATLAB入門教程-初學(xué)者必看

    MATLAB入門教程-初學(xué)者必看
    發(fā)表于 06-28 15:39

    Linux初學(xué)者必看?。?!

    Linux初學(xué)者必看!?。?/div>
    發(fā)表于 01-07 21:35

    單片機(jī)入門秘籍,初學(xué)者必看

    初學(xué)者必看的單片機(jī)秘籍
    發(fā)表于 04-29 16:10

    PCB LAYOUT初學(xué)者必看!

    PCBLAYOUT技術(shù)大全---初學(xué)者必看! PROTEL相關(guān)疑問 1.原理圖常見錯誤: (1)ERC報告管腳沒有接入信號: a.創(chuàng)建封裝時給管腳定義了I/O屬性; b.創(chuàng)建元件或放置
    發(fā)表于 09-13 15:23 ?0次下載

    PSOC1初學(xué)者5個實驗,針對初學(xué)者的實驗

    PSOC1初學(xué)者5個實驗,針對初學(xué)者的實驗
    發(fā)表于 10-16 09:33 ?14次下載
    PSOC<b class='flag-5'>1</b><b class='flag-5'>初學(xué)者</b>5個實驗,針對<b class='flag-5'>初學(xué)者</b>的實驗

    初學(xué)者必看的基本電子技術(shù)概念

    初學(xué)者必看的基本電子技術(shù)概念
    發(fā)表于 05-17 11:41 ?0次下載

    初學(xué)者必看的電源測試項目要點及教程

    初學(xué)者必看的電源測試項目要點及教程
    發(fā)表于 07-01 14:09 ?29次下載

    初學(xué)者必看的LABVIEW工程師編程經(jīng)驗

    初學(xué)者必看的LABVIEW工程師編程經(jīng)驗
    發(fā)表于 07-12 14:24 ?29次下載

    ARM與嵌入式linux入門的建議(初學(xué)者必看)

    ARM與嵌入式linux入門的建議(初學(xué)者必看)(嵌入式開發(fā)培訓(xùn)怎么樣)-該文檔為ARM與嵌入式linux入門的建議(初學(xué)者必看)總結(jié)文檔,是一份很不錯的參考資料,具有較高參考價值,感
    發(fā)表于 08-04 10:02 ?15次下載
    ARM與嵌入式linux入門的建議(<b class='flag-5'>初學(xué)者</b><b class='flag-5'>必看</b>)

    初學(xué)者必看的單片機(jī)程序匯總

    初學(xué)者必看的單片機(jī)程序匯總
    發(fā)表于 09-15 14:33 ?49次下載

    初學(xué)者必看SpringBoo自動裝配原理2

    學(xué)習(xí)SpringBoot,絕對避不開自動裝配這個概念,這也是SpringBoot的關(guān)鍵之一 本人也是SpringBoot的初學(xué)者,下面的一些總結(jié)都是結(jié)合個人理解和實踐得出的,如果有錯誤或者疏漏,請一定一定一定(不是歡迎,是
    的頭像 發(fā)表于 04-07 11:03 ?518次閱讀

    初學(xué)者必看SpringBoo自動裝配原理3

    學(xué)習(xí)SpringBoot,絕對避不開自動裝配這個概念,這也是SpringBoot的關(guān)鍵之一 本人也是SpringBoot的初學(xué)者,下面的一些總結(jié)都是結(jié)合個人理解和實踐得出的,如果有錯誤或者疏漏,請一定一定一定(不是歡迎,是
    的頭像 發(fā)表于 04-07 11:03 ?513次閱讀
    <b class='flag-5'>初學(xué)者</b><b class='flag-5'>必看</b>的<b class='flag-5'>SpringBoo</b><b class='flag-5'>自動</b><b class='flag-5'>裝配</b>原理3

    初學(xué)者必看SpringBoo自動裝配原理4

    學(xué)習(xí)SpringBoot,絕對避不開自動裝配這個概念,這也是SpringBoot的關(guān)鍵之一 本人也是SpringBoot的初學(xué)者,下面的一些總結(jié)都是結(jié)合個人理解和實踐得出的,如果有錯誤或者疏漏,請一定一定一定(不是歡迎,是
    的頭像 發(fā)表于 04-07 11:03 ?590次閱讀
    <b class='flag-5'>初學(xué)者</b><b class='flag-5'>必看</b>的<b class='flag-5'>SpringBoo</b><b class='flag-5'>自動</b><b class='flag-5'>裝配</b>原理4