一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

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

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

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

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

jf_78858299 ? 來源:CSDN ? 作者:CC_且聽風(fēng)吟 ? 2023-04-07 11:03 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

4. BeanDefinition結(jié)構(gòu)

既然講到了BeanDefinition,我們來看一下BeanDefinition里面究竟定義了些什么

讓我們點進AbstractBeanDefinition這個類,一探究竟

哇!好多成員變量,整個人都要看暈了@_@

我們來重點關(guān)注以下三個成員:

private volatile Object beanClass;
private int autowireMode = AUTOWIRE_NO;
private ConstructorArgumentValues constructorArgumentValues;

4.1 beanClass

這個屬性決定了該Bean定義的真正class到底是誰,接下來我們來做點實驗

我們定義兩個Bean類,A和B

@Component
public class A {
    @Value("我是AAA")
    private String name;
}
@Component
public class B {
    @Value("我是BBB")
    private String name;
}

接下來我們實現(xiàn)上面的BeanFactoryPostProcessor接口,來創(chuàng)建一個自定義的bean后置處理器

/**
 * 自定義的bean后置處理器
 * 通過這個MyBeanPostProcessor來修改bean定義的屬性
 * @author dzzhyk
 */
public class MyBeanPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        GenericBeanDefinition defA = (GenericBeanDefinition) beanFactory.getBeanDefinition("a");
        System.out.println("這里是MyBeanPostProcessor,我拿到了:" + defA.getBeanClassName());
    }
}

最后在XML配置文件中開啟包掃描

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

注意: 這里不要使用JavaConfig類來配置bean,不然會報如下錯誤

ConfigurationClassBeanDefinition cannot be cast to org.springframework.beans.factory.support.GenericBeanDefinition

這個錯誤出自這一句:

GenericBeanDefinition defA = (GenericBeanDefinition) beanFactory.getBeanDefinition("a");

最后,我們創(chuàng)建一個測試類:

public class Test {
    @org.junit.Test
    public void test(){
        ClassPathXmlApplicationContext ca = new ClassPathXmlApplicationContext("applicationContext.xml");
        A aaa = ca.getBean("a", A.class);
        System.out.println("最終拿到了==> " + aaa);
    }
}

測試運行!

這里是MyBeanPostProcessor,我拿到了:pojo.A
最終拿到了==> A(name=我是AAA, b=B(name=我是BBB))

可以看到MyBeanPostProcessor成功拿到了A的Bean定義,并且輸出了提示信息

接下來讓我們做點壞事

我們在MyBeanPostProcessor中修改A的Bean對象,將A的beanClass修改為B.class

System.out.println("這里是MyBeanPostProcessor,我修改了:"+ defA.getBeanClassName() + " 的class為 B.class");
// 把A的class改成B
defA.setBeanClass(B.class);

重新運行Test類,輸出了一些信息后:報錯了!

這里是MyBeanPostProcessor,我拿到了:pojo.A
這里是MyBeanPostProcessor,我修改了:pojo.A 的class為 B.class

BeanNotOfRequiredTypeException: 
 Bean named 'a' is expected to be of type 'pojo.A' but was actually of type 'pojo.B'

我要拿到一個A類對象,你怎么給我一個B類對象呢?這明顯不對

綜上所述,我們可以得出beanClass屬性控制bean定義的類

4.2 autowireMode

我們繼續(xù)看第二個屬性:autowireMode,自動裝配模式

我們在AbstractBeanDefinition源碼中可以看到:

private int autowireMode = AUTOWIRE_NO;

自動裝配模式默認是AUTOWIRE_NO,就是不開啟自動裝配

可選的常量值有以下四種:不自動裝配,通過名稱裝配,通過類型裝配,通過構(gòu)造器裝配

  • AUTOWIRE_NO
  • AUTOWIRE_BY_NAME
  • AUTOWIRE_BY_TYPE
  • AUTOWIRE_CONSTRUCTOR

接下來我們來模擬一個自動裝配場景,仍然是A和B兩個類,現(xiàn)在在A類中添加B類對象

@Component
public class A {
    @Value("我是AAA")
    private String name;
    @Autowired
    private B b;
}

我們希望b對象能夠自動裝配,于是我們給他加上了@Autowired注解,其他的完全不變,我們自定義的MyBeanPostProcessor中也不做任何操作,讓我們運行測試類:

這里是MyBeanPostProcessor,我拿到了:pojo.A
最終拿到了==> A(name=我是AAA, b=B(name=我是BBB))

自動裝配成功了!我們拿到的A類對象里面成功注入了B類對象b

現(xiàn)在問題來了,如果我把@Autowired注解去掉,自動裝配會成功嗎?

這里是MyBeanPostProcessor,我拿到了:pojo.A
最終拿到了==> A(name=我是AAA, b=null)

必然是不成功的

但是我就是想要不加@Autowired注解,仍然可以實現(xiàn)自動裝配,需要怎么做?

這時就要在我們的MyBeanPostProcessor中做文章了,加入如下內(nèi)容:

defA.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_NAME);

再輸出結(jié)果:

這里是MyBeanPostProcessor,我拿到了:pojo.A
最終拿到了==> A(name=我是AAA, b=B(name=我是BBB))

自動裝配成功了!這次我們可沒加@Autowired,在我們的自定義的bean后置處理器中設(shè)置了autowireMode屬性,也實現(xiàn)了自動裝配

綜上,autowireMode屬性是用來控制自動裝配模式的,默認值是AUTOWIRE_NO,即不自動裝配

4.3 constructorArgumentValues

constructorArgumentValues的字面含義是構(gòu)造器參數(shù)值

改變這個參數(shù)值,我們可以做到在實例化對象時指定特定的構(gòu)造器

話不多說,show me your code:

因為要研究構(gòu)造器,只能先”忍痛“關(guān)掉lombok插件,手寫一個pojo.Student類

/**
 * Student類
 * @author dzzhyk
 */
@Component
public class Student {
    private String name;
    private Integer age;

    public Student() {
        System.out.println("==>使用空參構(gòu)造器 Student()");
    }

    public Student(String name, Integer age) {
        this.name = name;
        this.age = age;
        System.out.println("==>使用雙參數(shù)構(gòu)造器 Student(String name, Integer age)");
    }
}

我們都知道,spring在實例化對象時使用的是對象的默認空參構(gòu)造器:

我們新建一個測試方法test

@Test
public void test(){
    ApplicationContext ca = new ClassPathXmlApplicationContext("applicationContext.xml");
    Student student = ca.getBean("stu", Student.class);
    System.out.println("==>" + student);
}

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

這里是MyBeanPostProcessor,我拿到了:pojo.Student
==>使用空參構(gòu)造器 Student()
==>pojo.Student@402e37bc

可以看到,確實使用了空參構(gòu)造器

但是如何指定(自定義)使用哪個構(gòu)造器呢?我根本看不見摸不著,Spring全幫我做了,實在是太貼心了。

接下來就聊聊constructorArgumentValues的使用:

我們在MyBeanPostProcessor中加入如下內(nèi)容,對獲取到的pojo.Student的bean定義進行操作:

ConstructorArgumentValues args = new ConstructorArgumentValues();
args.addIndexedArgumentValue(0, "我指定的姓名");
args.addIndexedArgumentValue(1, 20);
defStu.setConstructorArgumentValues(args);

再次運行test:

這里是MyBeanPostProcessor,我拿到了:pojo.Student
==>使用雙參數(shù)構(gòu)造器 Student(String name, Integer age)
==>pojo.Student@2f177a4b

可以看到這次使用了雙參數(shù)構(gòu)造器

有人會好奇ConstructorArgumentValues到底是個什么東西,我點進源碼研究一番,結(jié)果發(fā)現(xiàn)這個類就是一個普通的包裝類,包裝的對象是ValueHolder,里面一個List一個Map

而ValueHolder這個對象繼承于BeanMetadataElement,就是構(gòu)造器參數(shù)的一個包裝類型

通過這個例子我們可以看到ConstructorArgumentValues就是用來管控構(gòu)造器參數(shù)的,指定這個值會在進行bean注入的時候選擇合適的構(gòu)造器。

5. 裝配對象

現(xiàn)在我們把目光放回到SpringBoot的自動裝配上來,原來在真正進行bean實例化對象前,我們前面還有這些過程,尤其是存在使用后置處理器BeanFactoryPostProcessor來對bean定義進行各種自定義修改的操作。

經(jīng)過上面我們漫長的研究過程,我們終于可以回答第一個問題了:

自動裝配的對象:Bean定義 (BeanDefinition)

聲明:本文內(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

    文章

    340

    瀏覽量

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

    關(guān)注

    0

    文章

    5

    瀏覽量

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

    關(guān)注

    0

    文章

    7

    瀏覽量

    740
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點推薦

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

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

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

    PCB LAYOUT技術(shù)大全---初學(xué)者必看!
    發(fā)表于 01-09 18:43

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

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

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

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

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

    初學(xué)者必看的單片機秘籍
    發(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)建元件或放置元件時修改了不一致的grid屬性
    發(fā)表于 09-13 15:23 ?0次下載

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

    PSOC1初學(xué)者5個實驗,針對初學(xué)者的實驗
    發(fā)表于 10-16 09:33 ?14次下載
    PSOC1<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 ?31次下載

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

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

    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é)者必看的單片機程序匯總

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

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

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

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

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