spring學習筆記00 helloword-IOC&DI概述-配置bean-屬性配置細節

注意:有些文字放在代碼裏,雖然看起來不是很舒服,是因爲不放在代碼段裏面,有些如< > 這樣的符號會被轉義;

1.spring的helloword:

        這裏介紹一個新的eclipse插件:spring tool suit這個是用於spring的eclipse的插件,可以方
    便關於spring的框架開發。
1).ioc(依賴注入):
    注意:一共五個架包,一個兩個java類,一個spring的bean的配置文件
    ----------------------------------------------------------------------------------------
    bean的配置文件:
<?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 -->
    <bean id="helloword" class="com.spring.Helloword"> <!-- id標示,從IOC容器中獲取bean實例會用到 -->
        <!-- name對應set方法  value是賦的值-->
        <property name="name" value="spring"></property>
    </bean>
</beans>
    java文件01:
    package com.spring;
            public class Helloword {
                private String name;
                public void setName(String name) {
                    System.out.println("set.......");
                    this.name = name;
                }

                public void hello(){
                    System.out.println("heillo:"+name);
                }
                //無參構造器
                public Helloword(){
                    System.out.println("helloword.......con");
                }
            }
        java文件02package com.spring;
            import org.springframework.context.ApplicationContext;
            import org.springframework.context.support.ClassPathXmlApplicationContext;
            public class Main {
                public static void main(String[] a) {
                    // TODO Auto-generated constructor stub
                    //1.創建spring的ioc容器
                //注意:在new的時候,調用了bean相應類的無參構造方法,並且調用了set方法 傳入了參數;
                    //具體了可以把最後兩條語句註釋掉;
        ApplicationContext ctx =new  ClassPathXmlApplicationContext("spring.xml");
                    //2.從IOC容器中獲取bean實例:
                    Helloword hello= (Helloword)ctx.getBean("helloword");
                    hello.hello();
                }
            }

2.IOC和DI

        依賴注入的方式:屬性注入;構造器注入;
        IOC(Inversion of Control):其思想是反轉資源獲取的方向. 傳統的資源查找方式要求組件向容器發起請求查找資源. 作爲
    迴應, 容器適時的返回資源. 而應用了 IOC 之後, 則是容器主動地將資源推送給它所管理的組件, 組件所要做的僅是選擇一
    種合適的方式來接受資源. 這種行爲也被稱爲查找的被動形式;
        DI(Dependency Injection) — IOC 的另一種表述方式:即組件以一些預先定義好的方式(例如: setter 方法)接受來自如容
    器的資源注入. 相對於 IOC 而言,這種表述更直接;
        Spring 4.x 新特性:泛型依賴注入;
        bean 之間的關係:繼承;依賴;
        bean 的作用域:singleton;prototype;WEB 環境作用域;

3.配置bean:

        (反射,無參構造器)
        class的全類名,通過反射的方式在IOC的容器中創建bean,所以要求bean中必須有無參構造器;
        id:表示容器中的bean(id是Bean 的名稱):
            在IOC容器中必須是唯一的;
            若 id 沒有指定,Spring 自動將權限定性類名作爲 Bean 的名字;
            id 可以指定多個名字,名字之間可用逗號、分號、或空格分隔;              
        IOC的實現(兩種方式):Beanfactory(是spring框架的基礎設施)和     applicationcontext(面向開發者),幾乎所有的應用場
    合都直接使用applicationcontext而非beanfactory;無論使用何種方式,配置文件是相同的;
        applicationcontext有兩個主要的實現類:
            1.ClassPathXmlApplicationContext:從 類路徑下加載配置文件;
            2.FileSystemXmlApplicationContext: 從文件系統中加載配置文件;
        ConfigurableApplicationContext 擴展於 ApplicationContext,新增加兩個主要方法:refresh() 和 close(), 讓 Applicat
        ionContext 具有啓動、刷新和關閉上下文的能力
        ApplicationContext 在初始化上下文時就實例化所有單例的 Bean;
        WebApplicationContext 是專門爲 WEB 應用而準備的,它允許從相對於 WEB 根目錄的路徑中完成初始化工作;
        spring 3種依賴注入的方式:1.屬性注入;2.構造器注入;3.工廠方法注入(很少使用,不推薦使用);
        屬性注入:
            1.屬性注入即通過 setter 方法注入Bean 的屬性值或依賴的對象
            2.屬性注入使用 <property> 元素, 使用 name 屬性指定 Bean 的屬性名稱,value 屬性               或 <value> 子節點指定屬性值 
            3.<屬性注入是實際應用中最常用的注入方式>
        配置文件:
                <!-- 配置bean 通過屬性注入-->
                <!-- id標示  -->
                    <bean id="helloword" class="com.spring.Helloword"> 
                        <!-- name對應set方法  value是賦的值  調用類中的setter方法-->
                        <property name="name" value="spring"></property> 
                    </bean>
        構造器注入:
            通過構造方法注入Bean 的屬性值或依賴的對象,它保證了 Bean 實例在實例化後就可以使用。
            構造器注入在 <constructor-arg> 元素裏聲明屬性, <constructor-arg> 中沒有 name 屬性
        注意:使用構造器注入屬性值可以指定參數的位置(index)和參數的類型(type);  
            <bean id="car" class="com.spring.Car">
                    <constructor-arg value="Auti" index="0"></constructor-arg>
                    <constructor-arg value="ShangHai" index="1"></constructor-arg>
                    <constructor-arg value="300000" index="2"></constructor-arg>    
            </bean>

            <bean id="car2" class="com.spring.Car">
                    <constructor-arg value="Baoma" type="java.lang.String"></constructor-arg>
                    <constructor-arg value="Shanghai" type="java.lang.String"></constructor-arg>
                    <constructor-arg value="240" type="int"></constructor-arg>
            </bean>

java代碼:

                            public static void main(String[] a) {
                                // TODO Auto-generated constructor stub
                                //1.創建spring的ioc容器
                                //注意:在new的時候,調用了bean相應類的無參構造方法,並且調用了set方法 傳入了參數;
                                //具體了可以把最後1. 2. 3. 4. 兩條語句註釋掉;
        ApplicationContext ctx =new  ClassPathXmlApplicationContext("spring.xml");
                                //2.從IOC容器中獲取bean實例:
            Helloword hello= (Helloword)ctx.getBean("helloword"); // 實例化   調用無參構造
                                hello.hello();
                                    Car car=(Car)ctx.getBean("car");// 1.
                                    System.out.println(car);            //2.
                                    Car var=(Car)ctx.getBean("car2");  //3. 
                                System.out.println(var);      //4.
                            }

解釋看註解:

<bean id="person" class="com.spring.Person">        
        <property name="age" value="45"></property>
        <property name="name" value="renchenhao"></property>
        <!-- 非基本類型數據 引用型數據 可以用內部bean定義也行 -->
        <!-- <property name="car" ref="car2"></property> -->
        <!-- 內部bean 不能被外部引用 -->
        <property name="car">
            <bean class="com.spring.Car">
            <constructor-arg value="ford"></constructor-arg>
            <constructor-arg value="changha" type="java.lang.String"></constructor-arg>
            <constructor-arg value="2000000" type="int"></constructor-arg>
            </bean>
        </property>
    </bean>

注意:
1.使用構造函數注入的時候,可以不需要無參構造函數;
2.使用屬性注入的時候,必須要有無參構造;

4.屬性配置細節:

1.若字面值中包含特殊字符比如<>,可以使用 "<![CDATA[ 特殊字符  ]]>" 把字面值包裹起來。
2.屬性值可以用value子節點配置:
        <bean id="car2" class="com.spring.Car">
            <constructor-arg value="Baoma" type="java.lang.String"></constructor-arg>
            <constructor-arg value="Shanghai" type="java.lang.String"></constructor-arg>
            <constructor-arg type="int">
            <value>267</value><!-- value字節點進行配置 -->
            </constructor-arg>
        </bean>
3.基本數據類型及其封裝類、String 等類型都可以採取字面值注入的方式
4.要使 Bean 能夠相互訪問,就必須在 Bean 配置文件中指定對 Bean 的引用,在 Bean 的配置文件中, 可以通過 <ref> 元素或者添加一個ref的子節點,其中屬性爲Bean或構造器參數指定對Bean的引用;
5.注入參數詳解:null 值和級聯屬性:
    1).null 值:
        <bean id="person2" class="com.spring.Person">       
            <constructor-arg value="renchea"></constructor-arg>
            <constructor-arg value="4000000"></constructor-arg>
            <constructor-arg><null/></constructor-arg><!-- <null/> 是特有的寫法,爲null值必須這麼寫-->
        </bean>

注意:在設置value的值得時候:如果始終報如下異常:

Error creating bean with name 'person2' defined in class path resource [spring.xml]: Could not resolve matching constructor (hint: specify index/type/name arguments for simple parameters to avoid type ambiguities)  

那就是你的value值的類型和構造方法的參數類型對不上等這一系列的問題;

    2).級聯屬性賦值:
        <bean id="person3" class="com.spring.Person">       
                <constructor-arg value="22222"></constructor-arg>
                <constructor-arg value="121325"></constructor-arg>
                <constructor-arg ref="car"></constructor-arg>
        <!--  爲級聯屬性賦值,注意:屬性需要先初始化後纔可以爲級聯屬性賦值.否則會有異常,和struts2不同,struts2可以自動生成,很多時候我們用不着爲級聯屬性賦值,還有因爲下面用了property所以在Car中必須要有maxSpeed的setter方法; -->
                <property name="car.maxSpeed" value="5000"></property>
        </bean>

6.集合屬性:
1).List集合:

配置 java.util.List 類型的屬性, 需要指定 <list>  標籤, 在標籤裏包含一些元素. 這些標籤可以通過 <value> 指定簡單的常量值, 通過 <ref> 指定對其他 Bean 的引用. 通過<bean> 指定內置 Bean 定義. 通過 <null/> 指定空元素. 甚至可以內嵌其他集合.
    //在pojo Person類中的數據類型是這樣的,集合的數據類型;
    private List<Car> cars;
    <bean id="person2" class="com.spring.Person">       
        <property name="age" value="45"></property>
        <property name="name" value="renchenhao"></property>
        <property name="cars">
            <list>          
                <ref bean="car"/><!-- 通過 <ref> 指定對其他 Bean 的引用 -->           
                <bean class="com.spring.Car"> <!-- 通過<bean> 指定內置 Bean 定義 -->
                    <constructor-arg value="ford"></constructor-arg>
                    <constructor-arg value="changh" type="java.lang.String"></constructor-arg>
                    <constructor-arg value="9000000" type="int"></constructor-arg>
                </bean>         
                <null/> <!-- 通過null指定空元素 -->
            </list>
        </property> 
    </bean>

==========================================================
注意(遇到的問題):

-- 在pojo類中如有如下屬性():
    private List<Car> cars;
    private Car car;
    在spring的配置文件bean節點中不知道爲什麼只要是以屬性注入(構造器方法沒試過)的方式給car屬性賦值的時候,一運行都會變成cars屬性;
以下是兩種bean配置方法不同,效果一樣:
<!-- 使用內部bean的方法: -->>
 <bean id="person" class="com.spring.Person">       
        <property name="age" value="40"></property>
        <property name="name" value="renchenhao"></property>
        <property name="car">
            <bean  class="com.spring.Car">
                <constructor-arg value="ford"></constructor-arg>
                <constructor-arg value="changha" type="java.lang.String"></constructor-arg>
                <constructor-arg value="2000000" type="int"></constructor-arg>
            </bean>
        </property>
    </bean>

OR

<!-- 以下是引用的方法: -->
     <bean id="person" class="com.spring.Person">       
        <property name="age" value="40"></property>
        <property name="name" value="renchenhao"></property>
        <property name="car" ref="car2"></property>
    </bean>

以上兩種bean配置方法都是輸出同樣的結果;
pojo類的源碼:

package com.spring;
import java.util.List;

import com.spring.*;
public class Person {
    private String name;
    private int age;
    private List<Car> cars;
    private Car car;

    public Person() {
        super();
    }
    public Person(String name, int age, List<Car> cars) {
        super();
        this.name = name;
        this.age = age;
        this.cars = cars;
    }

    public Car getCar() {
        return car;
    }
    public void setCar(Car car) {
        this.car = car;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public List<Car> getCars() {
        return cars;
    }
    public void setCars(List<Car> cars) {
        this.cars = cars;
    }
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + ", cars=" + cars + "]";
    }



}

控制檯輸出結果: Person [name=renchenhao, age=40, cars=null]

疑惑:爲什麼明明屬性名指定爲car還是在給cars賦值,並且爲空,希望日後能解決,也希望看這篇博客的大神們能幫我解惑,十分感謝;

===========================================================

2). 數組的定義和 List 一樣, 都使用 <list>配置 java.util.Set 需要使用 <set> 標籤, 定義元素的方法與 List 一樣,這裏就不貼代碼了;

3).Map集合:
(Map集合一樣可以配置內部bean,具體的方法參照前面的方法;)

-Java.util.Map 通過 <map> 標籤定義, <map> 標籤裏可以使用多個 <entry> 作爲子標籤. 每個條目包含一個鍵和一個值;
-必須在 <key> 標籤裏定義鍵,因爲鍵和值的類型沒有限制, 所以可以自由地爲它們指定 <value>, <ref>, <bean><null> 元素;
-可以將 Map 的鍵和值作爲 <entry> 的屬性定義: 簡單常量使用 key 和 value 來定義; Bean 引用通過 key-ref 和 value-ref 屬性定義;
<bean id="person2" class="com.spring.Person">       
        <property name="age" value="45"></property>
        <property name="name" value="renchenhao"></property>
        <property name="cars">
            <map>               <!-- value-ref的屬性用的是bean的id  -->
                <entry key="SS" value-ref="car2"></entry>
                <entry key="AA" value-ref="car"></entry>
            </map>
        </property>
    </bean>

還有一種形式:

注意:entry節點的value屬性的值爲String類型,這樣設置的前提是,Map的泛型爲Map<String,String>或者Map不指定泛型;

<bean id="person2" class="com.spring.Person">       
        <property name="age" value="45"></property>
        <property name="name" value="renchenhao"></property>
        <property name="cars">
            <map>               
                <entry key="SS" value="car2"></entry>
                <entry>
                    <key><value>car-KEY</value></key><!-- 這是key -->
                    <value>car-value</value><!-- 這是值 -->
                </entry>                        
            </map>
        </property>
    </bean>

控制檯輸出結果:

Person [name=renchenhao, age=45, cars={SS=Car [brand=Baoma, corp=Shanghai, price=0.0, maxSpeed=267], car-KEY=car-value}]

4). java.util.Properties

使用 <props> 定義 java.util.Properties, 該標籤使用多個 <prop> 作爲子標籤. 每個 <prop> 標籤必須定義 key 屬性,在key屬性中寫入屬性值. 
//java代碼:
package com.spring;

import java.util.Properties;

public class DataSource {
    private Properties properties;
    public Properties getProperties() {
        return properties;
    }
    public void setProperties(Properties properties) {
        this.properties = properties;
    }
    public DataSource() {
        super();
    }
    @Override
    public String toString() {
        return "DataSource [properties=" + properties + "]";
    }

}
<!-- bean配置:  -->
    <bean id="datasource" class="com.spring.DataSource">
        <property name="properties">        
            <props>         
                <prop key="user">user</prop>
                <prop key="password">password</prop>
                <prop key="url">localhst:8080/test</prop>
                <prop key="driverClass">com.jdbc.driver</prop>
            </props>
        </property>     
    </bean>

控制檯輸出結果:
DataSource [properties={driverClass=com.jdbc.driver, user=user, url=localhst:8080/test, password=password}]
5).使用 utility scheme 定義集合:
—使用基本的集合標籤定義集合時, 不能將集合作爲獨立的 Bean 定義, 導致其他 Bean 無法引用該集合, 所以無法在不同 Bean 之間共享集合;
—可以使用 util schema 裏的集合標籤定義獨立的集合 Bean. 需要注意的是, 必須在 根元素裏添加 util schema 定義(就是必須要添加util的命名空間);

<!-- 配置單例的集合bean,以供多個bean進行引用,需要導入util的命名空間 -->
     <util:list id="cars">
        <ref bean="car"></ref>
        <ref bean="car2"></ref>
    </util:list> 
    <bean id="person3" class="com.spring.Person">
        <property name="name" value="jack"></property>
        <property name="age" value="49"></property>
        <property name="cars" ref="cars"></property>
    </bean>

6).使用 p 命名空間使用p命名空間的前提是必須導入p命名空間:

<!-- 通過p的命名空間爲bean的屬性賦值! 相對與傳統的配置方式更加簡介!  -->
<bean id="person5" class="com.spring.Person" p:age="30" p:name="renchenlkja" p:cars-ref="cars"></bean>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章