spring上 -基於Xml配置bean筆記

银河小船儿發表於2024-10-09

4,Spring 內容

7,快速入門

需求:透過 Spring 的方式[配置檔案], 獲取 JavaBean: Monster 的物件, 並給該的物件屬性賦值, 輸出該物件資訊.

程式碼結構:

lib 目錄是自己建立的,然後再引入5個jar包

原始碼:

beans.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">
    <!--
            老韓解讀
            1. 配置monster物件/javabean
            2. 在beans中可以配置多個bean
            3. bean表示就是一個java物件
            4. class屬性是用於指定類的全路徑->spring底層使用反射建立
            5. id屬性表示該java物件在spring容器中的id, 透過id可以獲取到物件
            6. <property name="monsterId" value="100"> 用於給該物件的屬性賦值,沒有給就是預設值
        -->
    <bean class="com.hspedu.spring.bean.Monster" id="monster01">
        <property name="monsterID" value="100"/>
        <property name="name" value="牛魔王"/>
        <property name="skill" value="芭蕉扇"/>
    </bean>
</beans>

Monster.java

package com.hspedu.spring.bean;

public class Monster {
    private Integer monsterID;
    private String name;
    private String skill;

    //全參構造器
    public Monster(Integer monsterID, String name, String skill) {
        this.monsterID = monsterID;
        this.name = name;
        this.skill = skill;
    }

    //無參構造器一定要寫,Spring反射建立物件時,需要使用
    public Monster() {

    }

    public Integer getMonsterID() {
        return monsterID;
    }

    public void setMonsterID(Integer monsterID) {
        this.monsterID = monsterID;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSkill() {
        return skill;
    }

    public void setSkill(String skill) {
        this.skill = skill;
    }

    @Override
    public String toString() {
        return "Monster{" +
                "monsterID=" + monsterID +
                ", name='" + name + '\'' +
                ", skill='" + skill + '\'' +
                '}';
    }
}

SpringBeanTest.java

package com.hspedu.spring.test;

import com.hspedu.spring.bean.Monster;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringBeanTest {

    @Test
    public void getMonster() {
        //1. 建立容器 ApplicationContext
        //2. 該容器和容器配置檔案關聯
        ApplicationContext ioc =
                new ClassPathXmlApplicationContext("beans.xml");

        //3. 透過getBean獲取對應的物件
        //   預設返回的是Object , 但是執行型別Monster
        Object monster01 = ioc.getBean("monster01");

        //4. 輸出
        System.out.println("monster01=" + monster01);
        System.out.println("執行型別=" + monster01.getClass());

        //5. 也可以再獲取的時候,直接指定Class型別, 可以再次獲取
        Monster monster02 = ioc.getBean("monster01", Monster.class);
        System.out.println("monster01=" + monster01);
        System.out.println("執行型別=" + monster02.getClass());
    }
}

執行結果:

11,Spring容器結構剖析

25,Spring配置Bean的基本介紹

26,透過型別來獲取Bean

之前的快速入門是透過 id 來獲取Bean

程式碼結構,Monster.java 都沒變。

beans.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">
    <!--配置Monster,透過型別來獲取,要求 ioc 容器中的同一個類的 bean 只能有一個, 否則會丟擲異常-->
    <bean class="com.hspedu.spring.bean.Monster">
        <!--老韓解讀
        1.當我們給某個bean物件設定屬性的時候
        2.底層是使用對應的setter方法完成的, 比如setName()
        3.如果沒有這個方法,就會報錯
        -->
        <property name="monsterID" value="100"/>
        <property name="name" value="牛魔王"/>
        <property name="skill" value="芭蕉扇"/>
    </bean>
</beans>

SpringBeanTest.java

package com.hspedu.spring.test;

import com.hspedu.spring.bean.Monster;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringBeanTest {

    //透過Bean的型別來獲取物件
    @Test
    public void getBeanByType() {
        ApplicationContext ioc =
                new ClassPathXmlApplicationContext("beans.xml");
        //老師解讀,直接傳入class物件/型別
        Monster bean = ioc.getBean(Monster.class);
        System.out.println("bean=" + bean);
    }
}

執行結果:

28,透過指定構造器配置Bean

程式碼結構不變

Monster.java

package com.hspedu.spring.bean;

public class Monster {
    private Integer monsterID;
    private String name;
    private String skill;

    //全參構造器
    public Monster(Integer monsterID, String name, String skill) {
        System.out.println("Monster全參構造器被呼叫...");
        this.monsterID = monsterID;
        this.name = name;
        this.skill = skill;
    }

    //無參構造器一定要寫,Spring反射建立物件時,需要使用
    public Monster() {

    }

    public Integer getMonsterID() {
        return monsterID;
    }

    public void setMonsterID(Integer monsterID) {
        this.monsterID = monsterID;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSkill() {
        return skill;
    }

    public void setSkill(String skill) {
        this.skill = skill;
    }

    @Override
    public String toString() {
        return "Monster{" +
                "monsterID=" + monsterID +
                ", name='" + name + '\'' +
                ", skill='" + skill + '\'' +
                '}';
    }
}

beans.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">
    <!--配置Monster物件,並且指定構造器
    老師解讀
    1. constructor-arg標籤可以指定使用構造器的引數
    2. index表示構造器的第幾個引數 從0開始計算的
    3. 除了可以透過index 還可以透過 name / type 來指定引數方式
    4. 解除大家的疑惑, 類的構造器,不能有完全相同型別和順序的構造器,所以可以透過type來指定
    -->
    <bean class="com.hspedu.spring.bean.Monster" id = "monster01">
        <constructor-arg value="200" index="0"/>
        <constructor-arg value="白骨精" index="1"/>
        <constructor-arg value="吸人血" index="2"/>
    </bean>
    <bean class="com.hspedu.spring.bean.Monster" id="monster02">
        <constructor-arg value="200" name="monsterID"/>
        <constructor-arg value="白骨精" name="name"/>
        <constructor-arg value="吸人血" name="skill"/>
    </bean>
    <!--
    資料型別就是對應的 Java 資料型別, 按構造器引數順序
    -->
    <bean class="com.hspedu.spring.bean.Monster" id="monster03">
        <constructor-arg value="200" type="java.lang.Integer"/>
        <constructor-arg value="白骨精" type="java.lang.String"/>
        <constructor-arg value="吸人血" type="java.lang.String"/>
    </bean>
</beans>

SpringBeanTest.java

package com.hspedu.spring.test;

import com.hspedu.spring.bean.Monster;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringBeanTest {

    //透過構造器來設定屬性
    @Test
    public void setBeanByConstructor() {
        ApplicationContext ioc =
                new ClassPathXmlApplicationContext("beans.xml");
        Monster bean = ioc.getBean("monster01", Monster.class);
        System.out.println("bean=" + bean);
    }
}

執行結果:

30,透過ref來配置Bean

Service 物件的dao 屬性想引用 右邊 容器裡的dao,就是透過ref來實現bean物件的相互引用。

程式碼結構:

MemberDAOImpl.java

package com.hspedu.spring.dao;

//dao物件
public class MemberDAOImpl {
    //構造器
    public MemberDAOImpl() {
        System.out.println("MemberDAOImpl 構造器被執行...");
    }

    public void add() {
        System.out.println("MemberDAOImpl add() 方法被執行...");
    }
}

MemberServiceImpl.java

package com.hspedu.spring.service;

import com.hspedu.spring.dao.MemberDAOImpl;

public class MemberServiceImpl {
    private MemberDAOImpl memberDAO;

    public MemberDAOImpl getMemberDAO() {
        return memberDAO;
    }

    public void setMemberDAO(MemberDAOImpl memberDAO) {
        this.memberDAO = memberDAO;
    }

    public void add() {
        System.out.println("MemberServiceImpl add() 被呼叫...");
        memberDAO.add();
    }
}

beans.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">
    <!--配置MemberDAOImpl物件-->
    <bean class="com.hspedu.spring.dao.MemberDAOImpl" id="memberDAO"/>
    <!--配置MemberServiceImpl物件
            老韓解讀
            1. ref="memberDAO"表示  MemberServiceImpl物件屬性memberDAO引用的物件是id=memberDAO
            的物件
            2. 這裡就體現出spring容器的依賴注入
            3. 注意再spring容器中, 他是作為一個整體來執行的, 即如果你引用到一個bean物件, 對你配置的順序沒有要求
            4. 建議還是按順序,好處是閱讀的時候,比較方便
        -->
    <bean class="com.hspedu.spring.service.MemberServiceImpl" id="memberService">
        <property name="memberDAO" ref="memberDAO"/>
    </bean>
</beans>

SpringBeanTest.java

package com.hspedu.spring.test;

import com.hspedu.spring.bean.Monster;
import com.hspedu.spring.service.MemberServiceImpl;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringBeanTest {

    //透過ref來設定bean屬性
    @Test
    public void setBeanByRef() {
        ApplicationContext ioc =
                new ClassPathXmlApplicationContext("beans.xml");
        MemberServiceImpl memberService = ioc.getBean("memberService", MemberServiceImpl.class);
        memberService.add();
    }
}

執行結果:

32,透過內部Bean來配置屬性

上一節的程式碼結構不變,只修改 beans.xml 和 SpringBeanTest.java

beans.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">
    <!--配置MemberServiceImpl物件-使用內部bean-->
    <bean class="com.hspedu.spring.service.MemberServiceImpl" id="memberService">
        <!--自己配置一個內部bean-->
        <property name="memberDAO">
            <bean class="com.hspedu.spring.dao.MemberDAOImpl"/>
        </property>
    </bean>

</beans>

SpringBeanTest.java

package com.hspedu.spring.test;

import com.hspedu.spring.bean.Monster;
import com.hspedu.spring.service.MemberServiceImpl;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringBeanTest {

    //透過內部bean設定屬性
    @Test
    public void setBeanByPro() {
        ApplicationContext ioc =
                new ClassPathXmlApplicationContext("beans.xml");
        MemberServiceImpl memberService = ioc.getBean("memberService", MemberServiceImpl.class);
        memberService.add();
    }
}

執行結果:

33,對List屬性進行配置

程式碼結構:

Master.java

package com.hspedu.spring.bean;

import java.util.*;

public class Master {
    private String name;

    private List<Monster> monsterList;
    private Map<String, Monster> monsterMap;
    private Set<Monster> monsterSet;

    //陣列
    private String[] monsterName;

    //Java基礎
    //這個 Properties 是 Hashtable 的子類 , 是 key-value 的形式
    //這裡 Properties key 和 value 都是 String
    private Properties pros;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List<Monster> getMonsterList() {
        return monsterList;
    }

    public void setMonsterList(List<Monster> monsterList) {
        this.monsterList = monsterList;
    }

    public Map<String, Monster> getMonsterMap() {
        return monsterMap;
    }

    public void setMonsterMap(Map<String, Monster> monsterMap) {
        this.monsterMap = monsterMap;
    }

    public Set<Monster> getMonsterSet() {
        return monsterSet;
    }

    public void setMonsterSet(Set<Monster> monsterSet) {
        this.monsterSet = monsterSet;
    }

    public String[] getMonsterName() {
        return monsterName;
    }

    public void setMonsterName(String[] monsterName) {
        this.monsterName = monsterName;
    }

    public Properties getPros() {
        return pros;
    }

    public void setPros(Properties pros) {
        this.pros = pros;
    }

    @Override
    public String toString() {
        return "Master{" +
                "name='" + name + '\'' +
                ", \nmonsterList=" + monsterList +
                ", \nmonsterMap=" + monsterMap +
                ", \nmonsterSet=" + monsterSet +
                ", \nmonsterName=" + Arrays.toString(monsterName) +
                ", \npros=" + pros +
                '}';
    }
}

Monster.java

package com.hspedu.spring.bean;

public class Monster {
    private Integer monsterID;
    private String name;
    private String skill;

    //全參構造器
    public Monster(Integer monsterID, String name, String skill) {
        this.monsterID = monsterID;
        this.name = name;
        this.skill = skill;
    }

    //無參構造器一定要寫,Spring反射建立物件時,需要使用
    public Monster() {

    }

    public Integer getMonsterID() {
        return monsterID;
    }

    public void setMonsterID(Integer monsterID) {
        this.monsterID = monsterID;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSkill() {
        return skill;
    }

    public void setSkill(String skill) {
        this.skill = skill;
    }

    @Override
    public String toString() {
        return "Monster{" +
                "monsterID=" + monsterID +
                ", name='" + name + '\'' +
                ", skill='" + skill + '\'' +
                '}';
    }
}

beans.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">
    <!--配置Master物件
    體會 spring 容器配置特點 依賴注入-非常靈活
    -->
    <bean class="com.hspedu.spring.bean.Master" id="master">
        <property name="name" value="太上老君"/>
        <!--給list屬性賦值-->
        <property name="monsterList">
            <list>
                <ref bean="monster01"/>
                <bean class="com.hspedu.spring.bean.Monster">
                    <property name="monsterID" value="100"/>
                    <property name="name" value="老鼠精"/>
                    <property name="skill" value="吃糧食"/>
                </bean>
            </list>
        </property>
    </bean>

    <bean class="com.hspedu.spring.bean.Monster" id="monster01">
        <property name="monsterID" value="1001"/>
        <property name="name" value="牛魔王"/>
        <property name="skill" value="芭蕉扇"/>
    </bean>
</beans>

SpringBeanTest.java

package com.hspedu.spring.test;

import com.hspedu.spring.bean.Master;
import com.hspedu.spring.bean.Monster;
import com.hspedu.spring.service.MemberServiceImpl;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringBeanTest {

    //給集合陣列屬性進行賦值
    @Test
    public void setBeanByCollection() {
        ApplicationContext ioc =
                new ClassPathXmlApplicationContext("beans.xml");
        Master master = ioc.getBean("master", Master.class);
        System.out.println("master=" + master);
    }
}

執行結果:

35,對Map屬性進行配置

程式碼結構和上一節的一樣,只有beans.xml 變了

beans.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">
    <!--配置Master物件
    體會 spring 容器配置特點 依賴注入-非常靈活
    -->
    <bean class="com.hspedu.spring.bean.Master" id="master">
        <property name="name" value="太上老君"/>
        <!--給map屬性賦值-->
        <property name="monsterMap">
            <map>
                <entry>
                    <key>
                        <value>monster01</value>
                    </key>
                    <!--這裡老師使用的外部bean,引入-->
                    <ref bean="monster01"/>
                </entry>

                <entry>
                    <key>
                        <value>monster02</value>
                    </key>
                    <!--這裡老師使用的外部bean,引入-->
                    <ref bean="monster02"/>
                </entry>
            </map>
        </property>
    </bean>

    <bean class="com.hspedu.spring.bean.Monster" id="monster01">
        <property name="monsterID" value="1001"/>
        <property name="name" value="牛魔王"/>
        <property name="skill" value="芭蕉扇"/>
    </bean>

    <bean class="com.hspedu.spring.bean.Monster" id="monster02">
        <property name="monsterID" value="1002"/>
        <property name="name" value="紅孩兒"/>
        <property name="skill" value="玩"/>
    </bean>
</beans>

執行結果:

36,對Set屬性進行配置

程式碼結構不變,只有 beans.xml 變了

beans.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">
    <!--配置Master物件
    體會 spring 容器配置特點 依賴注入-非常靈活
    -->
    <bean class="com.hspedu.spring.bean.Master" id="master">
        <property name="name" value="太上老君"/>
        <!--給set屬性賦值-->
        <property name="monsterSet">
            <set>
                <ref bean="monster01"/>
                <bean class="com.hspedu.spring.bean.Monster">
                    <property name="monsterID" value="666"/>
                    <property name="name" value="金角大王"/>
                    <property name="skill" value="吐水"/>
                </bean>
            </set>
        </property>
    </bean>

    <bean class="com.hspedu.spring.bean.Monster" id="monster01">
        <property name="monsterID" value="1001"/>
        <property name="name" value="牛魔王"/>
        <property name="skill" value="芭蕉扇"/>
    </bean>
</beans>

執行結果:

37,對Array屬性進行配置

程式碼結構不變,只有 beans.xml 變了

beans.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">
    <!--配置Master物件
    體會 spring 容器配置特點 依賴注入-非常靈活
    -->
    <bean class="com.hspedu.spring.bean.Master" id="master">
        <property name="name" value="太上老君"/>
        <!--給陣列屬性賦值
        老師多說一句: array標籤中使用 value 還是 bean , ref .. 要根據你的業務決定,陣列可以是字串陣列,也可以是Map陣列
        -->
        <property name="monsterName">
            <array>
                <value>小妖怪</value>
                <value>大妖怪</value>
                <value>老妖怪</value>
            </array>
        </property>
    </bean>
</beans>

執行結果:

38,對Properties屬性進行配置

程式碼結構不變,只有 beans.xml 變了

beans.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">
    <!--配置Master物件
    體會 spring 容器配置特點 依賴注入-非常靈活
    -->
    <bean class="com.hspedu.spring.bean.Master" id="master">
        <property name="name" value="太上老君"/>
        <!--給Properties屬性賦值 結構k(String)-v(String)-->
        <property name="pros">
            <props>
                <prop key="username">root</prop>
                <prop key="password">123456</prop>
                <prop key="ip">127.0.0.1</prop>
            </props>
        </property>
    </bean>
</beans>

執行結果:

39,使用util:list 進行配置

程式碼結構:

BookStore.java

package com.hspedu.spring.bean;

import java.util.List;

public class BookStore {
    private List<String> bookList;

    //無參構造器,如果你沒有其他的構造器,該無參構造器可以不寫
    //但是如果你有其他的構造器,則必須顯式的定義一下無參構造器
    public BookStore() {
    }

    public BookStore(List<String> bookList) {
        this.bookList = bookList;
    }

    public List<String> getBookList() {
        return bookList;
    }

    public void setBookList(List<String> bookList) {
        this.bookList = bookList;
    }

    @Override
    public String toString() {
        return "BookStore{" +
                "bookList=" + bookList +
                '}';
    }
}

beans.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" xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">
    <!--定義一個util:list 並且指定id 可以達到資料複用
    老師說明: 在使用util:list 名稱空間時候,需要引入相應的標籤, 一般來說透過alt+enter會自動加入
    , 如果沒有就手動新增一下即可.
    -->
    <util:list id="myBookList">
        <value>三國演義</value>
        <value>紅樓夢</value>
        <value>西遊記</value>
        <value>水滸傳</value>
    </util:list>

    <!--配置BookStore物件-->
    <bean class="com.hspedu.spring.bean.BookStore" id="bookStore">
        <property name="bookList" ref="myBookList"/>
    </bean>
</beans>

SpringBeanTest.java

package com.hspedu.spring.test;

import com.hspedu.spring.bean.BookStore;
import com.hspedu.spring.bean.Master;
import com.hspedu.spring.bean.Monster;
import com.hspedu.spring.service.MemberServiceImpl;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.awt.print.Book;

public class SpringBeanTest {

    //使用util:list名稱空間給屬性賦值
    @Test
    public void setBeanByUtilList() {
        ApplicationContext ioc =
                new ClassPathXmlApplicationContext("beans.xml");
        BookStore bookStore = ioc.getBean("bookStore", BookStore.class);
        System.out.println("bookStore=" + bookStore);
    }
}

執行結果:

40,屬性級聯賦值配置

就是在配置A類物件的時候,A類有一個B類屬性,同時給B類屬性的name賦個值。

例子:員工類中有一個部門屬性,在配置員工的時候,順便指定這個員工的部門名稱是什麼

程式碼結構:

Dept.java

package com.hspedu.spring.bean;

//部門類
public class Dept {
    private String name;

    public Dept() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Dept{" +
                "name='" + name + '\'' +
                '}';
    }
}

Emp.java

package com.hspedu.spring.bean;

//員工類
public class Emp {
    private String name;
    private Dept dept;

    public Emp() {
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Dept getDept() {
        return dept;
    }

    public void setDept(Dept dept) {
        this.dept = dept;
    }

    @Override
    public String toString() {
        return "Emp{" +
                "name='" + name + '\'' +
                ", dept=" + dept +
                '}';
    }
}

beans.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" xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">
    <!--配置Dept物件-->
    <bean class="com.hspedu.spring.bean.Dept" id="dept"/>
    <!--配置Emp物件-->
    <bean class="com.hspedu.spring.bean.Emp" id="emp">
        <property name="name" value="jack"/>
        <property name="dept" ref="dept"/>
        <!--這裡我希望給dept的name屬性指定值[級聯屬性賦值]-->
        <property name="dept.name" value="Java開發部門"/>
    </bean>
</beans>

SpringBeanTest.java

package com.hspedu.spring.test;

import com.hspedu.spring.bean.BookStore;
import com.hspedu.spring.bean.Emp;
import com.hspedu.spring.bean.Master;
import com.hspedu.spring.bean.Monster;
import com.hspedu.spring.service.MemberServiceImpl;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.awt.print.Book;

public class SpringBeanTest {

    //給屬性進行級聯賦值
    @Test
    public void setBeanByRelation() {
        ApplicationContext ioc =
                new ClassPathXmlApplicationContext("beans.xml");
        Emp emp = ioc.getBean("emp", Emp.class);
        System.out.println("emp=" + emp);
    }
}

執行結果:

41,透過靜態工廠獲取Bean

程式碼結構:

MyStaticFactory.java

package com.hspedu.spring.factory;

import com.hspedu.spring.bean.Monster;

import java.util.HashMap;
import java.util.Map;

//靜態工廠類-可以返回Monster物件
public class MyStaticFactory {
    private static Map<String, Monster> monsterMap;

    //使用 static 程式碼塊,進行初始化
    //在 java基礎的時候,講過的
    static {
        monsterMap = new HashMap<>();
        monsterMap.put("monster01", new Monster(100, "牛魔王", "芭蕉扇"));
        monsterMap.put("monster02", new Monster(200, "狐狸精", "美人計"));
    }

    //提供一個方法,返回Monster物件
    public static Monster getMonster(String key) {
        return monsterMap.get(key);
    }
}

beans.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" xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">
    <!--配置monster物件,透過靜態工廠獲取
    老師解讀
    1. 透過靜態工廠獲取/配置bean
    2. class 是靜態工廠類的全路徑
    3. factory-method 表示是指定靜態工廠類的哪個方法返回物件
    4. constructor-arg value="monster02" value是指定要返回靜態工廠的哪個物件
    -->
    <bean id="my_monster01" class="com.hspedu.spring.factory.MyStaticFactory"
          factory-method="getMonster">
        <constructor-arg value="monster01"/>
    </bean>
</beans>

SpringBeanTest.java

package com.hspedu.spring.test;

import com.hspedu.spring.bean.BookStore;
import com.hspedu.spring.bean.Emp;
import com.hspedu.spring.bean.Master;
import com.hspedu.spring.bean.Monster;
import com.hspedu.spring.factory.MyStaticFactory;
import com.hspedu.spring.service.MemberServiceImpl;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.awt.print.Book;

public class SpringBeanTest {

    //給屬性進行級聯賦值
    @Test
    public void setBeanByRelation() {
        ApplicationContext ioc =
                new ClassPathXmlApplicationContext("beans.xml");
        Monster monster = ioc.getBean("my_monster01", Monster.class);
        System.out.println("monster=" + monster);
    }
}

執行結果:

42,透過例項工廠獲取Bean

程式碼結構:

SpringBeanTest.java不變

MyInstanceFactory.java

package com.hspedu.spring.factory;

import com.hspedu.spring.bean.Monster;

import java.util.HashMap;
import java.util.Map;

public class MyInstanceFactory {
    private Map<String, Monster> monster_Map;

    //透過普通程式碼塊進行初始化
    {
        monster_Map = new HashMap<>();
        monster_Map.put("monster03", new Monster(100, "牛魔王~", "芭蕉扇~"));
        monster_Map.put("monster04", new Monster(200, "狐狸精~", "美人計~"));
    }

    //提供一個方法,返回Monster物件
    public Monster getMonster(String key) {
        return monster_Map.get(key);
    }
}

beans.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" xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">
    <!--配置monster物件, 透過例項工廠
    老韓解讀
    1. factory-bean 指定使用哪個例項工廠物件返回bean
    2. factory-method 指定使用例項工廠物件的哪個方法返回bean
    3. constructor-arg value="monster03" 指定獲取到例項工廠中的哪個monster
    -->
    <bean class="com.hspedu.spring.factory.MyInstanceFactory" id="myInstanceFactory"/>
    <bean id="my_monster01" factory-bean="myInstanceFactory" factory-method="getMonster">
        <constructor-arg value="monster03"/>
    </bean>
</beans>

執行結果:

44,透過FactoryBean獲取Bean

程式碼結構:

SpringBeanTest.java 不變

MyFactoryBean.java

package com.hspedu.spring.factory;

import com.hspedu.spring.bean.Monster;
import org.springframework.beans.factory.FactoryBean;

import java.util.HashMap;
import java.util.Map;

public class MyFactoryBean implements FactoryBean<Monster> {
    //這個 key 就是你配置的時候,指定要獲取的物件對應的key
    private String key;
    private Map<String, Monster> monster_map;

    //程式碼塊,完成初始化
    {
        monster_map = new HashMap<>();
        monster_map.put("monster03", new Monster(100, "牛魔王~", "芭蕉扇~"));
        monster_map.put("monster04", new Monster(200, "狐狸精~", "美人計~"));
    }

    public void setKey(String key) {
        this.key = key;
    }

    @Override
    public Monster getObject() throws Exception {
        return monster_map.get(key);
    }

    @Override
    public Class<?> getObjectType() {
        return Monster.class;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
}

beans.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" xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">
    <!--配置monster物件,透過FactoryBean獲取
    老師解讀
    1. class 指定使用的FactoryBean
    2. key表示就是 MyFactoryBean 屬性key
    3. value就是你要獲取的物件對應key
    -->
    <bean id="my_monster01" class="com.hspedu.spring.factory.MyFactoryBean">
        <property name="key" value="monster04"/>
    </bean>
</beans>

執行結果:

45,Bean配置資訊重用

程式碼結構不變,beans.xml,SpringBeanTest.java 變了

beans.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" xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">
    <!--配置Monster物件
    1. 如果bean指定了 abstract="true", 表示該bean物件, 是專門用於被繼承
    2. 本身這個bean就不能被獲取/例項化
    -->
    <bean id="monster12" class="com.hspedu.spring.bean.Monster" abstract="true">
        <property name="monsterID" value="100"/>
        <property name="name" value="蜈蚣精~"/>
        <property name="skill" value="蜇人~"/>
    </bean>

    <!--配置Monster物件-->
    <bean id="monster10" class="com.hspedu.spring.bean.Monster">
        <property name="monsterID" value="10"/>
        <property name="name" value="蜈蚣精"/>
        <property name="skill" value="蜇人"/>
    </bean>
    <!--
        老韓解讀
        1. 配置Monster物件
        2.但是這個物件的屬性值和 id="monster10"物件屬性一樣
        3.parent="monster10" 指定當前這個配置的物件的屬性值從 id=monster10的物件來
        -->
    <bean id="monster11" class="com.hspedu.spring.bean.Monster"
          parent="monster10"/>
</beans>

SpringBeanTest.java

package com.hspedu.spring.test;

import com.hspedu.spring.bean.BookStore;
import com.hspedu.spring.bean.Emp;
import com.hspedu.spring.bean.Master;
import com.hspedu.spring.bean.Monster;
import com.hspedu.spring.factory.MyStaticFactory;
import com.hspedu.spring.service.MemberServiceImpl;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.awt.print.Book;

public class SpringBeanTest {

    //透過FactoryBean獲取bean
    @Test
    public void getBeanByExtends() {
        ApplicationContext ioc =
                new ClassPathXmlApplicationContext("beans.xml");
        Monster monster11 = ioc.getBean("monster11", Monster.class);
        System.out.println("monster11=" + monster11);
    }
}

執行結果:

46,Bean建立順序1

程式碼結構:

Student.java

package com.hspedu.spring.bean;

public class Student {
    public Student() {
        System.out.println("Student()構造器被執行...");
    }
}

Department.java

package com.hspedu.spring.bean;

public class Department {
    public Department() {
        System.out.println("Department()構造器被執行...");
    }
}

beans.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" xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">
    <!--測試bean物件的建立順序
    老師解讀
    1. 在預設情況下, bean建立的順序是按照配置順序來的
    2. 但是如果我們增加了 depends-on="department01" 這時就會先建立id= department01物件
    -->
    <bean id="student01" class="com.hspedu.spring.bean.Student" depends-on="department01"/>
    <bean id="department01" class="com.hspedu.spring.bean.Department"/>
</beans>

SpringBeanTest.java

package com.hspedu.spring.test;

import com.hspedu.spring.bean.BookStore;
import com.hspedu.spring.bean.Emp;
import com.hspedu.spring.bean.Master;
import com.hspedu.spring.bean.Monster;
import com.hspedu.spring.factory.MyStaticFactory;
import com.hspedu.spring.service.MemberServiceImpl;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.awt.print.Book;

public class SpringBeanTest {

    //測試Bean建立順序
    @Test
    public void testBeanByCreate() {

        ApplicationContext ioc =
                new ClassPathXmlApplicationContext("beans.xml");
        System.out.println("ok");
    }
}

執行結果:

47,Bean建立順序2

程式碼結構和第30節的一樣,MemberServiceImpl.java , beans.xml, SpringBeanTest.java 變了

MemberServiceImpl.java

package com.hspedu.spring.service;

import com.hspedu.spring.dao.MemberDAOImpl;

public class MemberServiceImpl {
    private MemberDAOImpl memberDAO;

    public MemberServiceImpl() {
        System.out.println("MemberServiceImpl() 構造器被執行...");
    }

    public MemberDAOImpl getMemberDAO() {
        return memberDAO;
    }

    public void setMemberDAO(MemberDAOImpl memberDAO) {
        System.out.println("setMemberDAO()...");
        this.memberDAO = memberDAO;
    }

    public void add() {
        System.out.println("MemberServiceImpl add() 被呼叫...");
        memberDAO.add();
    }
}

beans.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" xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">

    <bean class="com.hspedu.spring.service.MemberServiceImpl" id="memberService">
        <property name="memberDAO" ref="memberDAO"/>
    </bean>
    <bean class="com.hspedu.spring.dao.MemberDAOImpl" id="memberDAO"/>
</beans>

SpringBeanTest.java

package com.hspedu.spring.test;

import com.hspedu.spring.bean.BookStore;
import com.hspedu.spring.bean.Emp;
import com.hspedu.spring.bean.Master;
import com.hspedu.spring.bean.Monster;
import com.hspedu.spring.factory.MyStaticFactory;
import com.hspedu.spring.service.MemberServiceImpl;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.awt.print.Book;

public class SpringBeanTest {

    //測試Bean建立順序
    @Test
    public void testBeanByCreate() {

        ApplicationContext ioc =
                new ClassPathXmlApplicationContext("beans.xml");
        System.out.println("ok");
    }
}

執行結果:

48,Bean的單例和多例項

使用細節需要 debug

程式碼結構:

Cat.java

package com.hspedu.spring.bean;

public class Cat {
    private Integer id;
    private String name;

    public Cat() {
        System.out.println("Cat() 被執行...");
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

beans.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" xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">

    <!--配置Cat物件
        老師解讀
        1. 在預設情況下 scope屬性是 singleton
        2. 在ioc容器中, 只要有一個這個bean物件
        3. 當程式設計師執行getBean時, 返回的的是同一個物件
        4. 如果我們希望每次getBean返回一個新的Bean物件,則可以scope="prototype"
        5. 如果bean的配置是 scope="singleton" lazy-init="true" 這時,ioc容器就不會提前建立該物件
           , 而是當執行getBean方法的時候,才會建立物件
    -->
    <bean id="cat" class="com.hspedu.spring.bean.Cat" scope="prototype">
        <property name="id" value="100"/>
        <property name="name" value="小花貓"/>
    </bean>
</beans>

SpringBeanTest.java

package com.hspedu.spring.test;

import com.hspedu.spring.bean.*;
import com.hspedu.spring.factory.MyStaticFactory;
import com.hspedu.spring.service.MemberServiceImpl;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.awt.print.Book;

public class SpringBeanTest {

    //測試Scope
    @Test
    public void testBeanScope() {

        ApplicationContext ioc =
                new ClassPathXmlApplicationContext("beans.xml");

        Cat cat = ioc.getBean("cat", Cat.class);
        Cat cat2 = ioc.getBean("cat", Cat.class);
        Cat cat3= ioc.getBean("cat", Cat.class);

        System.out.println("cat=" + cat);
        System.out.println("cat=" + cat2);
        System.out.println("cat=" + cat3);
    }
}

執行結果:

50,Bean的生命週期

程式碼結構:

House.java

package com.hspedu.spring.bean;

public class House {
    private String name;

    public House() {
        System.out.println("House() 構造器");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        System.out.println("House setName()=" + name);
        this.name = name;
    }

    //下面兩個方法是程式設計師來編寫的,根據自己的業務邏輯來寫,名字也不是固定的
    public void init() {
        System.out.println("House init()...");
    }

    public void destroy() {
        System.out.println("House destory()...");
    }
}

beans.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" xmlns:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">

    <!--配置House物件,演示整個Bean的生命週期
    老師解讀
    1. init-method="init" 指定bean的初始化方法 , 在setter方法後執行
    2. init方法執行的時機,有spring容器來控制
    3. destroy-method="destroy" 指定bean的銷燬方法, 在容器關閉的時候執行
    4. destroy方法執行的時機,有spring容器來控制
    -->
    <bean class="com.hspedu.spring.bean.House" id="house" init-method="init" destroy-method="destroy">
        <property name="name" value="北京豪宅"/>
    </bean>
</beans>

SpringBeanTest.java

package com.hspedu.spring.test;

import com.hspedu.spring.bean.*;
import com.hspedu.spring.factory.MyStaticFactory;
import com.hspedu.spring.service.MemberServiceImpl;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.awt.print.Book;

public class SpringBeanTest {

    //測試Bean的生命週期
    @Test
    public void  testBeanLife() {

        ApplicationContext ioc =
                new ClassPathXmlApplicationContext("beans.xml");
        House house = ioc.getBean("house", House.class);
        System.out.println("使用house=" + house);

        //關閉容器
        //1. 這裡又要考察大家的java基礎,用介面的形式
        //2. ioc的編譯型別 ApplicationContext , 執行型別 ClassPathXmlApplicationContext
        //3. 因為ClassPathXmlApplicationContext 實現了 ConfigurableApplicationContext
        //4. ClassPathXmlApplicationContext 是有close
        //5. 將ioc 轉成ClassPathXmlApplicationContext,再呼叫close
        //ioc.close();
        //關閉ioc容器.
        ((ConfigurableApplicationContext)ioc).close();

    }
}

執行結果:

51,配置Bean後置處理器

程式碼結構:

House.java

package com.hspedu.spring.bean;

public class House {
    private String name;

    public House() {
        System.out.println("House() 構造器");
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        System.out.println("House setName()=" + name);
        this.name = name;
    }

    //下面兩個方法是程式設計師來編寫的,根據自己的業務邏輯來寫,名字也不是固定的
    public void init() {
        System.out.println("House init()...");
    }

    public void destroy() {
        System.out.println("House destory()...");
    }

    @Override
    public String toString() {
        return "House{" +
                "name='" + name + '\'' +
                '}';
    }
}

MyBeanPostProcessor.java

package com.hspedu.spring.bean;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

//這是一個後置處理器,需要實現 BeanPostProcessor介面
public class MyBeanPostProcessor implements BeanPostProcessor {
    /**
     * 什麼時候被呼叫:在 bean 的 init方法前被呼叫,初始化之前完成某些任務
     * @param bean : 傳入的在IOC容器中建立/配置Bean
     *             就是 ioc 容器返回的 bean 物件, 如果這裡被替換會修改, 則返回的 bean 物件也會被修改
     * @param beanName: 傳入的在IOC容器中建立/配置Bean的id
     *                就是 ioc 容器配置的 bean 的名稱
     * @return Object: 程式設計師對傳入的bean進行修改/處理【如果有需要的話】,返回
     *               就是返回的 bean 物件
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessBeforeInitialization()... bean="
                + bean + " beanName=" + beanName);

        //初步體驗案例:如果型別是House的統一改成 上海豪宅
        //對多個物件進行處理/程式設計 --> 切面程式設計
        if (bean instanceof House) {
            ((House)bean).setName("上海豪宅");
        }
        return bean;
    }

    /**
    *什麼時候被呼叫: 在 bean 初始化之後完成某些任務
    * @param bean : 就是 ioc 容器返回的 bean 物件, 如果這裡被替換會修改, 則返
    回的 bean 物件也會被修改
    * @param beanName: 就是 ioc 容器配置的 bean 的名稱
    * @return Object: 就是返回的 bean 物件
    */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization()... bean="
                + bean + " beanName=" + beanName);
        return bean;
    }
}

beans02.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">

    <!--配置House物件-->
    <bean class="com.hspedu.spring.bean.House" id="house"
          init-method="init"
          destroy-method="destroy">
        <property name="name" value="大豪宅"/>
    </bean>

    <bean class="com.hspedu.spring.bean.House" id="house02"
          init-method="init"
          destroy-method="destroy">
        <property name="name" value="香港豪宅"/>
    </bean>

    <!--配置後置處理器物件
    老師解讀
    1. 當我們在beans02.xml 容器配置檔案 配置了 MyBeanPostProcessor
    2. 這時後置處理器物件,就會作用在該容器建立的Bean物件
    3. 已經是針對所有物件程式設計->切面程式設計AOP
    -->
    <bean class="com.hspedu.spring.bean.MyBeanPostProcessor" id="myBeanPostProcessor"/>
</beans>

SpringBeanTest.java

package com.hspedu.spring.test;

import com.hspedu.spring.bean.*;
import com.hspedu.spring.factory.MyStaticFactory;
import com.hspedu.spring.service.MemberServiceImpl;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.awt.print.Book;

public class SpringBeanTest {

    @Test
    public void beanPostProcessor() {
        ApplicationContext ioc =
                new ClassPathXmlApplicationContext("beans02.xml");

        House house = ioc.getBean("house", House.class);
        System.out.println("使用house=" + house);

        House house02 = ioc.getBean("house", House.class);
        System.out.println("使用house02=" + house02);
        ((ConfigurableApplicationContext)ioc).close();
    }
}

執行結果:

54,透過屬性檔案配置Bean

程式碼結構:

my.properties

monsterID=1000
name=jack
skill=hello

beans.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" xmlns:util="http://www.springframework.org/schema/util"
       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/util https://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <!--指定屬性檔案
    "location="classpath:my.properties" 表示指定屬性檔案的位置
    需要帶上 classpath
    屬性檔案有中文,需要將其轉為unicode編碼-->使用網上的工具轉
    -->
    <context:property-placeholder location="classpath:my.properties"/>
    <!--配置Monster物件
    1. 透過屬性檔案給monster物件的屬性賦值
    2. 這時我們的屬性值透過${屬性名}
    3. 這裡說的 屬性名 就是 my.properties檔案中的 k=v 的 k
    -->
    <bean class="com.hspedu.spring.bean.Monster" id="monster1000">
        <property name="monsterID" value="${monsterID}"/>
        <property name="skill" value="${skill}"/>
        <property name="name" value="${name}"/>
    </bean>
</beans>

SpringBeanTest.java

package com.hspedu.spring.test;

import com.hspedu.spring.bean.*;
import com.hspedu.spring.factory.MyStaticFactory;
import com.hspedu.spring.service.MemberServiceImpl;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.awt.print.Book;

public class SpringBeanTest {

    //透過屬性檔案給bean屬性賦值
    @Test
    public void setBeanByFile() {
        ApplicationContext ioc =
                new ClassPathXmlApplicationContext("beans.xml");
        Monster monster1000 = ioc.getBean("monster1000", Monster.class);
        System.out.println("monster1000=" + monster1000);
    }
}

執行結果:

56,自動裝配Bean

程式碼結構:

OrderDao.java

package com.hspedu.spring.dao;

public class OrderDao {
    public void saveOrder() {
        System.out.println("儲存 一個訂單...");
    }

}

OrderService.java

package com.hspedu.spring.service;

import com.hspedu.spring.dao.OrderDao;

public class OrderService {
    private OrderDao orderDao;

    public OrderDao getOrderDao() {
        return orderDao;
    }
    public void setOrderDao(OrderDao orderDao) {
        this.orderDao = orderDao;
    }

}

OrderAction.java

package com.hspedu.spring.web;

import com.hspedu.spring.service.OrderService;

public class OrderAction {
    private OrderService orderService;

    public OrderService getOrderService() {
        return orderService;
    }
    public void setOrderService(OrderService orderService) {
        this.orderService = orderService;
    }
}

beans.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" xmlns:util="http://www.springframework.org/schema/util"
       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/util https://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    <!--配置OrderDao物件-->
    <bean class="com.hspedu.spring.dao.OrderDao" id="orderDao"/>
    <!--配置OrderService物件
        老師解讀
        1. autowire="byType" 表示 在建立 orderService時,透過型別的方式 給物件屬性 自動完成賦值/引用
        2. 比如OrderService 物件有 private OrderDao orderDao
        3. 就會在容器中去找有沒有 OrderDao型別物件
        4. 如果有,就會自動的裝配, 老師提示如果是按照 byType 方式來裝配, 這個容器中,不能有兩個
          的OrderDao型別物件
        5. 如果你的物件沒有屬性,  autowire就沒有必要寫
        6. 其它類推..

        7. 如果我們設定的是 autowire="byName" 表示透過名字完成自動裝配
        8. 比如下面的 autowire="byName" class="com.hspedu.spring.service.OrderService"
           1) 先看 OrderService 屬性 private OrderDao orderDao
           2) 再根據這個屬性的setXxx()方法的 xxx 來找物件id
           3) public void setOrderDao() 就會找id=orderDao物件來進行自動裝配
           4) 如果沒有就裝配失敗
    -->
    <bean autowire="byType" class="com.hspedu.spring.service.OrderService" id="orderService"/>
    <!--配置OrderAction-->
    <bean autowire="byName" class="com.hspedu.spring.web.OrderAction" id="orderAction"/>

</beans>

SpringBeanTest.java

package com.hspedu.spring.test;

import com.hspedu.spring.bean.*;
import com.hspedu.spring.factory.MyStaticFactory;
import com.hspedu.spring.service.MemberServiceImpl;
import com.hspedu.spring.web.OrderAction;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.awt.print.Book;

public class SpringBeanTest {

    //透過自動裝配來對屬性賦值
    @Test
    public void setBeanByAutowire() {
        ApplicationContext ioc =
                new ClassPathXmlApplicationContext("beans.xml");
        OrderAction orderAction = ioc.getBean("orderAction", OrderAction.class);

        //驗證是否自動裝配上OrderService
        System.out.println(orderAction.getOrderService());
        //驗證是否自動裝配上OrderDao
        System.out.println(orderAction.getOrderService().getOrderDao());
    }
}

執行結果:

相關文章