色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

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

3天內不再提示

初學者必看的SpringBoo自動裝配原理2

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

4. BeanDefinition結構

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

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

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

我們來重點關注以下三個成員:

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;
}

接下來我們實現上面的BeanFactoryPostProcessor接口,來創建一個自定義的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");

最后,我們創建一個測試類:

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

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

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

private int autowireMode = AUTOWIRE_NO;

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

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

  • AUTOWIRE_NO
  • AUTOWIRE_BY_NAME
  • AUTOWIRE_BY_TYPE
  • AUTOWIRE_CONSTRUCTOR

接下來我們來模擬一個自動裝配場景,仍然是A和B兩個類,現在在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

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

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

必然是不成功的

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

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

defA.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_NAME);

再輸出結果:

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

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

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

4.3 constructorArgumentValues

constructorArgumentValues的字面含義是構造器參數

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

話不多說,show me your code:

因為要研究構造器,只能先”忍痛“關掉lombok插件,手寫一個pojo.Student類

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

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

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

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

我們新建一個測試方法test

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

運行可以得到下面結果:

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

可以看到,確實使用了空參構造器

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

接下來就聊聊constructorArgumentValues的使用:

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

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

再次運行test:

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

可以看到這次使用了雙參數構造器

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

而ValueHolder這個對象繼承于BeanMetadataElement,就是構造器參數的一個包裝類型

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

5. 裝配對象

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

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

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

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • spring
    +關注

    關注

    0

    文章

    340

    瀏覽量

    14338
  • 源碼分析
    +關注

    關注

    0

    文章

    5

    瀏覽量

    5546
  • 自動裝配
    +關注

    關注

    0

    文章

    7

    瀏覽量

    649
收藏 人收藏

    評論

    相關推薦

    protel技術大全--初學者必看

    protel技術大全--初學者必看
    發表于 08-04 10:36

    PSOC1初學者必看的10個實例

    PSOC1初學者必看的10個實例
    發表于 11-19 16:33

    MATLAB入門教程-初學者必看

    MATLAB入門教程-初學者必看
    發表于 06-28 15:39

    Linux初學者必看!!!

    Linux初學者必看!!!
    發表于 01-07 21:35

    單片機入門秘籍,初學者必看

    初學者必看的單片機秘籍
    發表于 04-29 16:10

    PCB LAYOUT初學者必看

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

    PSOC1初學者5個實驗,針對初學者的實驗

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

    初學者必看的基本電子技術概念

    初學者必看的基本電子技術概念
    發表于 05-17 11:41 ?0次下載

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

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

    初學者必看的LABVIEW工程師編程經驗

    初學者必看的LABVIEW工程師編程經驗
    發表于 07-12 14:24 ?29次下載

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

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

    初學者必看的單片機程序匯總

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

    初學者必看SpringBoo自動裝配原理1

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

    初學者必看SpringBoo自動裝配原理3

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

    初學者必看SpringBoo自動裝配原理4

    學習SpringBoot,絕對避不開自動裝配這個概念,這也是SpringBoot的關鍵之一 本人也是SpringBoot的初學者,下面的一些總結都是結合個人理解和實踐得出的,如果有錯誤或者疏漏,請一定一定一定(不是歡迎,是
    的頭像 發表于 04-07 11:03 ?641次閱讀
    <b class='flag-5'>初學者</b><b class='flag-5'>必看</b>的<b class='flag-5'>SpringBoo</b><b class='flag-5'>自動</b><b class='flag-5'>裝配</b>原理4
    主站蜘蛛池模板: 伊人久久青青草| 樱桃熟了A级毛片| 最新毛片网| 欧美国产精品久久久乱码| 99热视频这里只有久久精品| 久久久久国产一级毛片高清片| 亚洲午夜精品久久久久久抢| 九九黄色大片| 苍井空小公主qvod| 乌克兰美女x?x?y?y| 精品爽爽久久久久久蜜臀| 99久久蜜臀AV免费看蛮| 文中字幕一区二区三区视频播放| 国产精品久久久久久搜索 | 99爱在线精品视频网站| 婷婷午夜影院| 美美哒免费影视8| 国产毛片AV久久久久精品| 5g在线视讯年龄确认海外禁止进入 | 妹妹成人网| 国产成人亚洲精品老王| 18未满不能进的福利社| 午夜视频无码国产在线观看| 欧美精品做人一级爱免费| 国产午夜精品久久久久九九| 在线播放免费人成毛片视频| 色AV色婷婷96人妻久久久| 久久网站视频| 国产婷婷色一区二区三区在线 | 欧美成人免费观看久久| 韩国成人理伦片免费播放| 啊灬啊灬啊灬快高潮视频| 在线涩涩免费观看国产精品| 视频一区视频二区ae86| 欧洲内射XXX高清| 久久婷婷五月综合色情| 极品少妇高潮XXXXX| 国产手机在线视频| 国产精品高潮AV久久无码| 草莓视频在线观看完整高清免费| 2021国产精品国产精华|