亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > Java > 正文

詳解Spring中bean的幾種注入方式

2024-07-14 08:41:07
字體:
來源:轉載
供稿:網友

首先,要學習Spring中的Bean的注入方式,就要先了解什么是依賴注入。依賴注入是指:讓調用類對某一接口的實現類的實現類的依賴關系由第三方注入,以此來消除調用類對某一接口實現類的依賴。

Spring容器中支持的依賴注入方式主要有屬性注入、構造函數注入、工廠方法注入。接下來將為大家詳細介紹這三種依賴注入的方式以及它們的具體配置方法。

1.屬性注入

屬性注入即通過setXXX( )方法注入bean的屬性值或依賴對象。由于屬性注入方式具有可選擇性和靈活性高的特點,因此它也是實際開發中最常用的注入方式。

Spring首先會調用bean的默認構造函數實例化bean對象,然后再通過反射的方法調用set方法來注入屬性值。

屬性注入要求bean提供一個 默認的構造函數 ,并且得為需要注入的屬性提供 set方法 。

TIps:所謂默認的構造函數,即不帶參數的構造函數。如果類中沒有自定義任何構造函數,則系統(JVM)會自動生成一個不帶參的默認構造函數,如果類中顯式的自定義了有參數的構造函數,則系統就不會在自動生成默認構造函數,需要自己手動再加一個無參的構造函數。

下面通過一個實例來演示Spring中bean的屬性注入方式:

編寫一個user類:

package com.Kevin.bean;/** * 創建一個類測試bean的屬性注入方式 * @author Kevin * */public class User {    private String username;  public String getUsername() {    return username;  }  public void setUsername(String username) {    this.username = username;  }}

配置文件:

<?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.xsd"> <!-- bean definitions here -->  <!-- 配置對象 -->  <bean id="user" class="com.Kevin.bean.User">    <property name="username">      <value>Kevin</value>    </property>  </bean>  </beans>

其中,每個屬性值對應一個property標簽,name屬性值為類中屬性的名稱。在bean實現類中擁有與其對應的實現方法setUsername( )。

Tips:Spring只會檢查bean中是否含有setter方法,而對是否有對應的屬性變量則不作具體要求,但按照約定俗成的規則我們最好為其設定相應的屬性變量。

Spring中<property>標簽的命名規范:

  1. Spring的<property>標簽所指定的屬性名稱和bean實現類的setter方法滿足Sun JavaBean的屬性命名規范,即XXX的屬性對應setXXX( )的方法。

一般情況下,java的屬性變量名都以小寫字母開頭,但考慮到一些特殊意義的英文縮略詞,java bean也允許一些大寫字母開頭的變量名。但必須滿足以下兩點:

  1. 變量的前兩個字母要么全部大寫,要么全部小寫;
  2. 但以一般編程習慣來說,屬性名最好全部使用小寫字母,方便編程和閱讀。

對于屬性注入方式來說,只能人為的在配置文件中提供保證,而無法在語法級別提供保證。此時就需要使用構造函數注入這種方式,以此來更好的滿足要求。

2.構造函數注入

構造函數注入是除屬性注入之外的另一種常用的注入方式,它可以保證一些必要的屬性在bean實例化時就得到了設置,并在實例化后就可以使用。

使用構造函數注入的前提是: bean必須提供帶參的構造函數。

對于構造函數的注入,配置文件可以有以下幾種方式:

  1. 按類型匹配入參
  2. 按索引匹配入參
  3. 聯合使用類型和索引匹配入參
  4. 通過自身類型反射匹配入參

【按類型匹配入參方式】

編寫bean代碼:

package com.Kevin.bean;/** * 編寫bean測試按類型匹配入參方式 * @author Kevin * */public class Person {  private String name;  private Integer age;  public String getName() {    return name;  }  public void setName(String name) {    this.name = name;  }  public Integer getAge() {    return age;  }  public void setAge(Integer age) {    this.age = age;  }}

編寫配置文件:

<?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.xsd"> <!-- bean definitions here -->  <!-- 配置對象 -->  <bean id="person" class="com.Kevin.bean.Person">    <constructor-arg type="String">      <value>Kevin</value>    </constructor-arg>    <constructor-arg type="Integer">      <value>20</value>    </constructor-arg>  </bean>  </beans>

Spring的配置文件采用和元素標簽順序無關的配置策略,因此可以在一定程度上保證配置信息的確定性。

那么當bean中的構造函數的 多個類型參數一樣時 ,按照類型匹配入參的這種方式容易產生混淆,此時就需要使用另一種方式:按照索引匹配入參。

【按照索引匹配入參】

編寫bean代碼:

package com.Kevin.bean;/** * 編寫bean測試按照索引方式入參 * @author Kevin * */public class Student {  private String name;  private String gender;  private Double score;  public Student(String name, String gender, Double score) {    super();    this.name = name;    this.gender = gender;    this.score = score;  }}

配置文件編寫如下:

<?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.xsd"> <!-- bean definitions here -->  <!-- 配置對象 -->  <bean id="student" class="com.Kevin.bean.Student">    <constructor-arg index="0" value="Kevin"></constructor-arg>    <constructor-arg index="1" value="Male"></constructor-arg>    <constructor-arg index="2" value="66"></constructor-arg>  </bean>  </beans>

Tips: 在屬性注入時,Spring按java bean的規范確定配置 屬性 和對應的 setter方法 ,并使用java反射機制調用屬性的setter方法完成屬性注入。但java反射機制并 不會記住構造函數的入參名 ,因此我們不能通過制定構造函數的入參名稱來進行構造函數的配置,所以我們只能通過 入參的類型及索引 來間接完成構造函數的屬性注入。

【聯合使用類型和索引匹配入參】

在某些復雜的配置文件當中,需要使用type和index同時出馬才能完成構造函數的參數注入。下面使用一個實例來演示。

編寫bean:

package com.Kevin.bean;/** * 編寫bean測試聯合使用類型和索引匹配入參 * @author Kevin * */public class Teacher {  private String name;  private String address;  private double salary;  private int age;  public Teacher(String name, String address, double salary) {    super();    this.name = name;    this.address = address;    this.salary = salary;  }  public Teacher(String name, String address, int age) {    super();    this.name = name;    this.address = address;    this.age = age;  }}

在這個類中,有兩個重載的構造函數,他們都有三個參數,在這種情況下使用type和index的方法都不能完成要求,這時候就需要他們兩個屬性同時使用了。

配置文件:

<?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.xsd"> <!-- bean definitions here -->  <!-- 配置對象 -->  <bean id="teacher" class="com.Kevin.bean.Teacher">    <constructor-arg index="0" type="String">      <value>Kevin</value>    </constructor-arg>    <constructor-arg index="1" type="String">      <value>China</value>    </constructor-arg>    <constructor-arg index="2" type="int">      <value>20</value>    </constructor-arg>  </bean>  </beans>

可以看到其實重點在于第三個入參的類型,所以我們在配置文件中指定了索引和類型,這樣便可以使得Spring知道對哪個構造函數進行參數注入了。

Tips: 加入我們得配置文件中存在歧義問題,Spring容器是可以正常啟動的,并不會報錯,它將隨機采用一個匹配的構造函數實例化bean。而隨機選擇的構造函數可能并不是用戶所需要的,所以我們在編程時要小心避免出現這種歧義情況。

【通過自身類型反射匹配入參】

如果bean構造函數入參的類型是可辨別的,由于java反射機制可以獲取構造函數入參的類型,即使構造函數的注入不提供類型和索引的信息,Spring依舊可以完成構造函數信息的注入。例如下面實例中Manager類的構造函數的入參類型就是可以辨別的。

編寫Manager類:

package com.Kevin.bean;/** * 編寫Bean測試通過自身類型反射匹配入參方式 * @author Kevin * */public class Manager {  private String name;  private Double salary;  private Person person;  public Manager(String name, Double salary, Person person) {    super();    this.name = name;    this.salary = salary;    this.person = person;  } }

編寫配置文件:

<?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.xsd"> <!-- bean definitions here -->  <!-- 配置對象 -->  <bean id="manager" class="com.Kevin.bean.Manager">    <constructor-arg>      <value>Kevin</value>    </constructor-arg>    <constructor-arg>      <ref bean="user"/>    </constructor-arg>    <constructor-arg>      <ref bean="person"/>    </constructor-arg>  </bean>  </beans>

以上幾種方法都可以實現 構造函數參數的注入 ,但是為了避免問題的發生,還是建議使用 顯式的index和type 來配置構造函數的入參信息。

3.工廠方法注入

工廠方法是應用中被經常使用的設計模式,也是 控制反轉 和 單實例設計思想 的主要實現方法。工廠類負責創建一個或多個工廠類實例,工廠類方法一般以接口或抽象類變量的形式返回目標類實例。

工廠類對外屏蔽了目標類的實例化步驟,調用者甚至根本不用指定具體的目標類是什么。由于Spring容器以框架的方法提供工廠方法的功能,并以透明的方式開放給開發者。因此很少需要手工編寫工程方法。但在一些遺留系統或第三方類庫中還是會碰到工程方法,此時便可以使用Spring工廠注入的方法來進行Spring的注入。

Spring工廠注入的方法可以分為 靜態 和 非靜態 兩種。

【非靜態工廠方法】

有些工廠方法是非靜態的,必須實例化工廠類之后才能調用工廠方法。下面通過一個實例來演示。

編寫工廠類:

package com.Kevin.factorybean;/** * 編寫工廠類測試非靜態工廠方法注入 * @author Kevin * */public class BookFactory {  public Book buyBook(){    Book book = new Book();    book.setName("Think in Java");    return book;  }}

配置文件編寫:

<?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.xsd"> <!-- bean definitions here -->  <!-- 配置對象 -->  <bean id="bookFactory" class="com.Kevin.factorybean.BookFactory"></bean>  <bean id="book" factory-bean="bookFactory" factory-method="buyBook"></bean>  </beans>

由于bookFactory的工廠方法不是靜態的,因此需要先定義一個工廠類的bean,然后通過 factory-bean 屬性來引用工廠bean實例。再通過屬性 factory-method 來指定對應的工廠方法。

【靜態工廠方法】

很多工廠類方法都是靜態的,這意味著無需創建工廠類實例的情況下就可以調用工廠類方法。因此靜態工程方法比非靜態工廠方法的調用更加方便簡潔。下面通過一個實例來演示靜態工廠方法。

編寫factory類:

package com.Kevin.factorybean;/** * 編寫工廠類測試靜態工廠方法注入 * @author Kevin * */public class CarFactory {  public static Car createCar(){    Car car = new Car();    car.setBrand("Lamborghini");    return car;  }}

編寫配置文件:

<?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.xsd"> <!-- bean definitions here -->  <!-- 配置對象 -->  <bean id="car" class="com.Kevin.factorybean.Car" factory-method="createCar"></bean>  </beans>

總結

Spring提供了三種可供選擇的注入方式,但在實際應用中,我們究竟該選擇哪種注入方式,并沒有統一的標準,如下是一些可以參考的理由:

構造函數注入理由:

  1. 構造函數保證重要屬性預先設置;
  2. 無需提供每個屬性的setter方法,減少類的方法個數;
  3. 可以更好地封裝類變量,避免外部錯誤調用。

屬性注入理由:

  1. 屬性過多時,構造函數變的臃腫;
  2. 構造函數注入靈活性不強,有時需要為屬性注入null值;
  3. 多個構造函數時,配置上產生歧義,復雜度升高;
  4. 構造函數不利于類的繼承和擴展;
  5. 構造函數注入會引起循環依賴的問題。 

其實Spring為我們注入參數提供了這么多方法,那么這些方法必然有他們存在的道理,每個方法在某一問題上會有獨特的優勢,我們只需要按照我們具體的使用需求選擇適合的方法來使用就好了,但一般不太推薦工廠方法注入。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VeVb武林網。


注:相關教程知識閱讀請移步到JAVA教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
精品国产1区2区| 91精品国产91久久久久久吃药| 亚洲精品日韩丝袜精品| 国产xxx69麻豆国语对白| 国产免费亚洲高清| 美日韩丰满少妇在线观看| 夜夜嗨av色一区二区不卡| 欧美丰满片xxx777| 亚洲精品白浆高清久久久久久| 日韩免费看的电影电视剧大全| 国产精品白嫩美女在线观看| 奇米影视亚洲狠狠色| 亚洲欧美三级在线| 亚洲精品永久免费| 亚洲国产日韩欧美在线99| 国产精品情侣自拍| 黑人巨大精品欧美一区免费视频| 一区二区三区四区在线观看视频| 日韩欧美在线看| 国产成人精品视频在线| 国产亚洲在线播放| 亚洲图中文字幕| 日韩久久免费视频| 久久躁狠狠躁夜夜爽| 亚洲成人av中文字幕| 91精品在线一区| 中文字幕亚洲二区| 欧美精品电影免费在线观看| 亚洲视频在线看| 亚洲欧美日韩一区在线| 精品久久久久久久大神国产| 91黑丝在线观看| 国产精品国产亚洲伊人久久| 97在线观看视频| 欧美多人爱爱视频网站| 国产主播在线一区| 91亚洲午夜在线| 欧美国产日本高清在线| 亚洲一区二区三区xxx视频| 亚洲第一级黄色片| 国产欧美一区二区| 亚洲人成网站999久久久综合| 欧美专区福利在线| 亚洲天堂网站在线观看视频| 懂色av一区二区三区| 日韩精品免费在线视频观看| 91av免费观看91av精品在线| 国产日韩中文字幕| 一区二区三区黄色| 久久精品99无色码中文字幕| 亚洲精品国产suv| 精品国产一区二区三区久久狼黑人| 国产激情视频一区| 亚洲天堂日韩电影| 国产精品久久久久久亚洲影视| 国产69久久精品成人| 国语自产精品视频在免费| 久久久久久12| 亚洲天堂免费在线| 国产精品入口福利| 亚洲第一福利网| 久久69精品久久久久久国产越南| 91探花福利精品国产自产在线| 国产精品∨欧美精品v日韩精品| 久久精品2019中文字幕| 国产区亚洲区欧美区| 欧美性视频网站| 国产精品高潮视频| 欧美一区深夜视频| 亚洲欧美制服中文字幕| 国产精品白嫩初高中害羞小美女| 久久久久国产精品一区| 欧美成人精品在线观看| 美女啪啪无遮挡免费久久网站| 亚洲色图欧美制服丝袜另类第一页| 欧美裸体xxxx| 日韩国产高清视频在线| 亚洲天堂影视av| 丝袜美腿亚洲一区二区| 日韩欧美亚洲一二三区| 亚洲国产婷婷香蕉久久久久久| 国产精品18久久久久久首页狼| 亚洲一区美女视频在线观看免费| 日韩有码视频在线| www.亚洲男人天堂| 国产亚洲免费的视频看| 日韩成人中文字幕在线观看| 久久免费国产精品1| 欧美性猛交xxxx偷拍洗澡| 九九精品视频在线观看| 国产成人综合精品在线| 欧美在线视频导航| 97视频在线观看免费高清完整版在线观看| 91中文在线观看| 亚洲欧美日本伦理| 欧美大片在线影院| 中文字幕日韩精品在线观看| 中文字幕不卡av| 最新国产精品拍自在线播放| 欧美激情小视频| 亚洲欧美综合精品久久成人| 亚洲三级免费看| 日韩精品欧美国产精品忘忧草| 精品一区二区三区三区| 日韩精品一区二区三区第95| 国产婷婷色综合av蜜臀av| 日韩欧美亚洲国产一区| 久久久久久有精品国产| 在线精品播放av| 一本色道久久88亚洲综合88| 午夜精品福利电影| 91av在线播放| 亚洲国产精品视频在线观看| 精品视频一区在线视频| 色悠久久久久综合先锋影音下载| 国产一区二区三区直播精品电影| 欧美视频中文字幕在线| 亚洲综合在线中文字幕| 中文字幕欧美精品日韩中文字幕| 亚洲中国色老太| 最好看的2019年中文视频| 亚洲人成电影在线| 伊人久久大香线蕉av一区二区| 91精品视频专区| 日本伊人精品一区二区三区介绍| 91黑丝在线观看| 国产免费一区二区三区在线能观看| 亚洲美女福利视频网站| 国产精品高精视频免费| 亚洲欧美综合另类中字| 国产aⅴ夜夜欢一区二区三区| 精品久久久精品| 午夜精品久久久久久久白皮肤| 最近2019免费中文字幕视频三| 亚洲天堂一区二区三区| 亚洲精品美女久久| 色妞色视频一区二区三区四区| 亚洲黄色免费三级| 精品视频9999| 国产精品视频xxxx| 欧美伦理91i| 日韩av高清不卡| 综合国产在线观看| 亚洲色图综合久久| 性色av一区二区三区在线观看| 国产视频精品免费播放| 中文字幕综合在线| 久久精品这里热有精品| 在线色欧美三级视频| 久久视频在线直播| 国产精自产拍久久久久久蜜| 久久久久久久一区二区三区| 91av视频在线| www.亚洲人.com| 成人妇女免费播放久久久| 欧美成人精品一区二区三区| 亚洲淫片在线视频| 日韩国产高清污视频在线观看| 欧美激情一区二区三区成人| 九九综合九九综合| 久久久亚洲成人| 亚洲曰本av电影| 精品国内自产拍在线观看| 国产婷婷97碰碰久久人人蜜臀|