1. 程式人生 > >Spring IOC Bean裝配 --day07

Spring IOC Bean裝配 --day07

Spring IOC Bean裝配 --day07

碰到的問題,以及思考解決不在這裡寫,本人日記:記錄覺得需要記得常用描述,具體實現相關知識點。寫日記是為了梳理知識點加深記憶。可能缺少很多資訊,如果您看到給您道個歉

個人覺得總結的相當好的博文

一、概述

 IOC 控制反轉:傳統開發中,通過new來實現手動建立物件,IOC思想則是通過第三方來獲取物件,不管物件怎麼來的,你需要就跟他(Spring)說就行了,實現原理也是基於反射。

IOC 容器:
 Spring 提供 IoC 容器來管理和容納我們所開發的各種各樣的 Bean,並且我們可以從中獲取各種釋出在 Spring IoC 容器裡的 Bean,並且通過描述可以得到它。

bean的理解,很好的一篇博文
Spring 容器設計
盜圖:
ioc 介面
 1)BeanFactory: Spring IoC 容器所定義的最底層介面(getBean方法引數:Bean.class、“beanName”、“beanName”,Bean.class)。
 2)ApplicationContext:Spring IoC 容器所定義最高階介面之一,使用最廣泛的介面,功能強大,支援方法較多。

二、簡單實現

匯入相關包(過)Maven管理
pojo類

public class Clothes {
    public Clothes()
    {
        System.out.
println("一件衣服被建立了"+System.identityHashCode(this)); } private String color; private int size; public String getColor() { return color; } public void setColor(String color) { this.color = color; } public int getSize() { return size; }
public void setSize(int size) { this.size = size; } public void destory(){ //System.identityHashCode(Object)方法可以返回物件的記憶體地址 System.out.println("這件衣服被銷燬了"+System.identityHashCode(this)); } }

xml 配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean class="my.test.Clothes" id="clothes" lazy-init="true"  destroy-method="destory" >
        <property name="color" value="red"/>
        <property name="size" value="33"/>
    </bean>
</beans>

測試類

        //初始化容器
        ApplicationContext applicationContext =new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
        //getBean方法拿到物件
        Clothes clothes1 = (Clothes)applicationContext.getBean("clothes");
        //列印結果資訊
        System.out.println(clothes1.getColor()+clothes1.getSize());

結果


一件衣服被建立了1740846921
衣服顏色:red衣服尺碼:33

三、Bean的裝配

 根據優先順序排序 順序3→2→1,但由於種種因素的限制有些裝配無法實現,只能採用次一級優先順序方法來實現裝配。

1.xml檔案中顯示配置(二中配置)

 簡單易懂,當使用第三方類的時候,有些類並不是我們開發的,我們無法修改裡面的程式碼只能使用xml進行配置。

<bean id="唯一標識,並不是必須 可以使用name代替 沒有定義預設是全限定名#(0++)按定義次數遞加" class="類的全限定名">
    <!--設值注入簡單型別-->
    <property name="屬性名" value="屬性值" />
    <!--屬性也是一個Bean 通過refy引用-->
    <property name="屬性名" ref="另一個Bean的id或者name"/>
     <property name="屬性名" >
        <ref bean="另一個Bean的id或者name"/>
     </property>
    <property name="屬性名">
           <value>另一種值寫入方式</value>
           <!--除了value 還可以 是Set、Map、List、Array、Properties 等-->
           <!--和各自子節點的對應關係
                list\Set\Array:value
                Map:entry
                Properties :property(必填key屬性)     
           -->
    </property>

</bean>

名稱空間裝配
c-名稱空間:用於構造注入簡化寫法:

<!--未引入名稱空間-->
<bean....>
<constructor-arg name="id" value="1" />
<constructor-arg name="name" value="學生1"/>
</bean>
<!-- 引入c- 名稱空間後-->
<bean name="student2" class="pojo.Student"
      c:id="2" c:name="學生2"/>
<!--如果需要設定引用的話在對應引數名後加上 (-ref) 比如:c:name-ref="beanId"
    也可以用下標代替屬性名
    如:c:_0=""、c:_1=""

  -->

p-名稱空間:簡化設定注入寫法,寫法和c-名稱空間簡寫規則一樣c換成p

util-名稱空間:簡化集合類元素

<!-- 引入util-名稱空間之前 -->
<property name="list">
   <list>
       <ref bean="bean1"/>
       <ref bean="bean2"/>
   </list>
</property>

<!-- 引入util-名稱空間之後 -->
<util:list id="list">
   <ref bean="bean1"/>
   <ref bean="bean2"/>
</util:list>

元素 描述
<util:constant> 引用某個型別的 public static 域,並將其暴露為 bean
<util:list> 建立一個 java.util.List 型別的 bean,其中包含值或引用
<util:map> 建立一個 java.util.map 型別的 bean,其中包含值或引用
<util:properties> 建立一個 java.util.Properties 型別的 bean
<util:property-path> 引用一個 bean 的屬性(或內嵌屬性),並將其暴露為 bean
<util:set> 建立一個 java.util.Set 型別的 bean,其中包含值或引用

通常一個配置檔案寫大量Bean配置資訊會變得十分臃腫,可以通過import引入其他配置檔案
寫法:

<import resource="bean.xml" />

2.java類和介面中配置

 可以減少xml檔案中複雜的手動配置,可以實現自動裝配。
兩種使IOC容器能發現Bean的方法:
 1)包掃描
  定義掃描的包資源,讓Spring IOC去掃描相應的包,將對應Bean裝配進來
 2)自動裝配
  通過註解定義,使得一些依賴關係可以通過註解完成。

@Component、@Value、@ComponentScan
簡單規則:

@Component(value=“Bean的id,如果不寫預設類名”)
@value(“下面屬性的注入值”)
@ComponentScan:掃描當前包路徑下的所有被@Compoent註解標記的pojo類。

示例程式碼:

//測試pojo類
package my.test;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component(value="clothes")
public class Clothes {
    public Clothes()
    {
        System.out.println("一件衣服被建立了"+System.identityHashCode(this));
    }
    @Value("red")
    private     String color;
    @Value("31")
    private     int size;
    //getter setter and others
}

//測試類
@ComponentScan
public class SpringTest {
    public static void main(String args[])
    {
        //初始化容器
        //ApplicationContext applicationContext =new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Clothes.class);

        //getBean方法拿到物件
        Clothes clothes1 = (Clothes)applicationContext.getBean("clothes",Clothes.class);
        //列印結果資訊
        System.out.println("衣服顏色:"+clothes1.getColor()+"衣服尺碼:"+clothes1.getSize());

    }

}

實驗成功

@Value(只能注入簡單型別值,不能注入物件)、@ComponentScan(只能掃描當前包)

@ComponentScan配置項:
 basePackages:Spring 根據它配置的資訊去掃描對應的包以及子包,裝配配置好的Bean
 basePackageClasses:他會根據設定的類去自動查詢到類所在的包,將配置好的Bean裝配進來。

@ComponentScan(basePackages = "my.test")
@ComponentScan(basePackageClasses = my.test.Clothes.class)

注意:basePackages 和 basePackageClasses 選擇
 basePackages較簡單且易讀,因為設定過程中使用字串傳遞引數,寫入錯誤不會提示,在大量重構的專案中,經常需要修改報名 不適合使用。basePackageClasses 中包名變化,原來寫入資訊和當前包名不符合,或類名不符 IDE中會報錯

@Autowired
 通過它可以實現物件自動裝配,用它標記一個自定義型別屬性,等到Spring IOC 容器已經定位好所有Bean的時候,按照這個屬性的自定義型別,去查詢Bean,對這個屬性實現裝配

建立一個公司型別,讓衣服類擁有一個公司屬性,並用@Autowired
程式碼:

//公司

@Component(value="company")
public class Company {
      @Value("小公司")
      private  String companyName;

      public String getCompanyName() {
            return companyName;
      }

      public void setCompanyName(String companyName) {
            this.companyName = companyName;
      }
}
//衣服加入對公司所在包的掃描、或掃描公司類
    @Autowired
    private Company company;
    //getter、setter..

測試成功。

注意:
 @Autowired預設能找到相應的Bean注入,如果注入失敗會報錯。解決方法:設定@Autowired(required = false) 設定注入失敗不會報錯。
 註解不僅僅能配置在屬性之上,還允許方法配置/
 當發現多個相同型別的Bean 無法確定注入哪一個Bean:@Primary 標記一個類,這個類滿足條件會被優先注入,@Qualifier指定注入的Bean的id

3.隱式Bean發現自動裝配

@Bean
 上面通過@Component來裝配Bean,該註解使用在類上,引用第三方包的時候很不方便,&Bean可以用到到第三方包的方法上。
測試程式碼:

@Configuration//註解相當於 XML 檔案的根元素,必須要,有了才能解析其中的 @Bean
public class BeanTest {
    @Bean(name = "testName")
    public String  test()
    {
        System.out.println("測試Bean方法");
        return "必須有返回值";
    }

}
//測試類
    // 在 pojo 包下掃描
        ApplicationContext context = new AnnotationConfigApplicationContext("my.test");
        context.getBean("testName");
        ((AnnotationConfigApplicationContext) context).close();
//測試成功

@Bean只用於方法,方法必須有返回值否則報錯

Bean配置項

屬性 作用
name: 是一個字串陣列,允許配置多個 BeanName
autowire: 標誌是否是一個引用的 Bean 物件,預設值是 Autowire.NO
initMethod: 自定義初始化方法
destroyMethod: 自定義銷燬方法