天天看點

Spring概述及基于XML的IOC配置1. spring概述2. IoC的概念和作用2.3 ioc的概念和作用3. spring基于XML的IOC4. IOC中的bean标簽5. spring的依賴注入

Spring概述及基于XML的IOC配置

  • 1. spring概述
    • 1.1 spring是什麼
    • 1.2 spring的優勢
    • 1.3 spring的體系結構
  • 2. IoC的概念和作用
    • 2.1 程式的耦合和解耦
    • 2.2 工廠模式解耦
  • 2.3 ioc的概念和作用
  • 3. spring基于XML的IOC
    • 3.1 實作
    • 3.2 細節
      • 3.2.1 spring中的工廠類的結構圖
      • 3.2.2 BeanFactory和ApplicationContext的差別
      • 3.2.3 ApplicationContext的三個實作類
  • 4. IOC中的bean标簽
    • 4.1 建立bean對象的三種方式
    • 4.2 bean的作用範圍
    • 4.3 bean的生命周期
  • 5. spring的依賴注入
    • 5.1 依賴注入的概念
    • 5.2 構造函數注入
    • 5.3 set 方法注入(常用)
    • 5.4 注入集合資料

1. spring概述

1.1 spring是什麼

Spring是分層的 Java SE/EE應用 full-stack 輕量級開源架構,以==IoC(Inverse Of Control:反轉控制)==和 ==AOP(Aspect Oriented Programming:面向切面程式設計)==為核心,提供了展現層SpringMVC和持久層 Spring JDBC 以及業務層事務管理等衆多的企業級應用技術,還能整合開源世界衆多著名的第三方架構和類庫,逐漸成為使用最多的Java EE 企業應用開源架構。

1.2 spring的優勢

  1. 友善解耦,簡化開發

    通過 Spring提供的IoC容器,可以将對象間的依賴關系交由 Spring進行控制,避免寫死所造成的過度程式耦合。使用者也不必再為單例模式類、屬性檔案解析等這些很底層的需求編寫代碼,可以更專注于上層的應用。

  2. AOP 程式設計的支援

    通過 Spring的 AOP 功能,友善進行面向切面的程式設計,許多不容易用傳統OOP 實作的功能可以通過 AOP 輕松應付。

  3. 聲明式事務的支援

    可以将我們從單調煩悶的事務管理代碼中解脫出來,通過聲明式方式靈活的進行事務的管理,提高開發效率和品質。

  4. 友善程式的測試

    可以用非容器依賴的程式設計方式進行幾乎所有的測試工作,測試不再是昂貴的操作,而是随手可做的事情。

  5. 友善內建各種優秀架構

    Spring可以降低各種架構的使用難度,提供了對各種優秀架構(Struts、Hibernate、Hessian、Quartz等)的直接支援。

  6. 降低JavaEE API 的使用難度

    Spring對JavaEE API(如 JDBC、JavaMail、遠端調用等)進行了薄薄的封裝層,使這些 API 的使用難度大為降低。

  7. Java 源碼是經典學習範例

    Spring的源代碼設計精妙、結構清晰、匠心獨用,處處展現着大師對Java 設計模式靈活運用以及對 Java技術的高深造詣。它的源代碼無意是 Java 技術的最佳實踐的範例。

1.3 spring的體系結構

Spring概述及基于XML的IOC配置1. spring概述2. IoC的概念和作用2.3 ioc的概念和作用3. spring基于XML的IOC4. IOC中的bean标簽5. spring的依賴注入

2. IoC的概念和作用

2.1 程式的耦合和解耦

耦合:程式間的依賴關系,包括類之間的依賴和方法間的依賴。

解耦:降低程式間的依賴關系

實際開發中應該做到,編譯期不依賴,運作時才依賴。

解耦的思路:

第一步:使用反射來建立對象,而避免使用new關鍵字。

第二步:通過讀取配置檔案來擷取要建立的對象全限定類名

2.2 工廠模式解耦

建立持久層接口和實作類

public interface IAccountDao {
    /**
     * 模拟儲存帳戶
     */
    void saveAccount();
}
           
public class AccountDaoImpl implements IAccountDao {
    public void saveAccount() {
        System.out.println("儲存了帳戶");
    }
}
           

建立業務層接口和實作類

public interface IAccountService {
    /**
     * 模拟儲存帳戶
     */
    void saveAccount();
}
           
public class AccountServiceImpl implements IAccountService {
    private IAccountDao accountDao = new AccountDaoImpl();
    public void saveAccount() {
        accountDao.saveAccount();
    }
}
           

模拟表現層

public class Client {
    public static void main(String[] args) {
        IAccountService as = new AccountServiceImpl();
        as.saveAccount();
    }
}
           

建立BeanFactory類

一個建立Bean對象的工廠

Bean:在計算機英語中,有可重用元件的含義。

JavaBean:用java語言編寫的可重用元件。

javabean>=實體類

它就是建立我們的service和dao對象的。

第一個:需要一個配置檔案來配置我們的service和dao

配置的内容:唯一辨別=全限定類名(key=value)

第二個:通過讀取配置檔案中配置的内容,反射建立對象

我的配置檔案可以是xml也可以是properties

public class BeanFactory {
    //定義一個Properties對象
    private static Properties props;
    //定義一個Map用于存放我們要建立的對象,稱為容器
    private static Map<String,Object> beans;
    //使用靜态代碼塊為Properties對象指派
    static{
        try {
            //執行個體化對象
            props = new Properties();
            //擷取properties檔案的流對象
            InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
            props.load(in);
            //執行個體化容器
            beans = new HashMap<String,Object>();
            //取出配置檔案中所有的key
            Enumeration keys = props.keys();
            //周遊枚舉
            while(keys.hasMoreElements()){
                String key = keys.nextElement().toString();
                //根據key擷取value
                String beanPath = props.getProperty(key);
                //反射建立對象
                Object value = Class.forName(beanPath).newInstance();
                //把keyvalue存入到容器
                beans.put(key,value);
            }
        } catch (Exception e) {
            throw new ExceptionInInitializerError("初始化properties失敗!");
        }
    }

   
    /**
     * 根據bean的名稱擷取bean對象
     * @param beanName
     * @return
     */
    public static Object getBean(String beanName){
        Object bean = null;
        String beanPath = props.getProperty(beanName);
        try {
            bean = Class.forName(beanPath).newInstance();//每次都會調用預設構造函數建立對象
        }  catch (Exception e) {
            e.printStackTrace();
        }
        return bean;
    }
}
           

建立一個bean.properties

accountService=com.wyj.service.impl.AccountServiceImpl
accountDao=com.wyj.dao.impl.AccountDaoImpl
           

修改表現層、業務層

IAccountService as = (IAccountService)BeanFactory.getBean("accountService");

 private IAccountDao accountDao = (IAccountDao)BeanFactory.getBean("accountDao");
           

2.3 ioc的概念和作用

Spring概述及基于XML的IOC配置1. spring概述2. IoC的概念和作用2.3 ioc的概念和作用3. spring基于XML的IOC4. IOC中的bean标簽5. spring的依賴注入
Spring概述及基于XML的IOC配置1. spring概述2. IoC的概念和作用2.3 ioc的概念和作用3. spring基于XML的IOC4. IOC中的bean标簽5. spring的依賴注入

3. spring基于XML的IOC

3.1 實作

  1. 建立持久層、業務層接口和實作類
  2. 導入依賴
<dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.0.2.RELEASE</version>
        </dependency>
           
  1. 建立bean.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">
    <!--把對象的建立交給spring來管理-->
    <bean id="accountService" class="com.wyj.service.impl.AccountServiceImpl"></bean>

    <bean id="accountDao" class="com.wyj.dao.impl.AccountDaoImpl"></bean>
</beans>
           
  1. 測試代碼
public static void main(String[] args) {
        //1.擷取核心容器對象
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        //ApplicationContext ac = new FileSystemXmlApplicationContext("C:\\Users\\Desktop\\bean.xml")
        //2.根據id擷取bean對象
        IAccountService as = (IAccountService)ac.getBean("accountService");
        IAccountDao adao = ac.getBean("accountDao",IAccountDao.class);

        System.out.println(as);
        System.out.println(adao);

    }
           

3.2 細節

3.2.1 spring中的工廠類的結構圖

Spring概述及基于XML的IOC配置1. spring概述2. IoC的概念和作用2.3 ioc的概念和作用3. spring基于XML的IOC4. IOC中的bean标簽5. spring的依賴注入

3.2.2 BeanFactory和ApplicationContext的差別

BeanFactory才是 Spring 容器中的頂層接口。

ApplicationContext是它的子接口。

BeanFactory和ApplicationContext的差別

建立對象的時間點不一樣。

ApplicationContext:隻要一讀取配置檔案,預設情況下就會建立對象。

BeanFactory:什麼使用什麼時候建立對象。

Spring概述及基于XML的IOC配置1. spring概述2. IoC的概念和作用2.3 ioc的概念和作用3. spring基于XML的IOC4. IOC中的bean标簽5. spring的依賴注入

3.2.3 ApplicationContext的三個實作類

==ClassPathXmlApplicationContext:==它可以加載類路徑下的配置檔案,要求配置檔案必須在類路徑下。不在的話,加載不了。(更常用)

==FileSystemXmlApplicationContext:==它可以加載磁盤任意路徑下的配置檔案(必須有通路權限)

==AnnotationConfigApplicationContext:==它是用于讀取注解建立容器的。

4. IOC中的bean标簽

4.1 建立bean對象的三種方式

  1. 使用預設構造函數建立

    在spring的配置檔案中使用bean标簽,配以id和class屬性後且沒有其他屬性和标簽時, 采用的是預設構造函數建立bean對象,此時如果類中沒有預設構造函數,對象無法建立

  1. 使用工廠中的靜态方法建立對象(使用某個類中的靜态方法建立對象,并存入容器)

    id 屬性:指定 bean 的 id,用于從容器中擷取

    class 屬性:指定靜态工廠的全限定類名

    factory-method 屬性:指定生産對象的靜态方法

public class StaticFactory {
    public static IAccountService getAccountService(){
        return new AccountServiceImpl();
    }
}
           
  1. 使用普通工廠中的方法建立對象(使用某個類總的方法建立對象,并存入容器)

先把工廠的建立交給 spring 來管理。

然後在使用工廠的 bean 來調用裡面的方法

factory-bean 屬性:用于指定執行個體工廠 bean 的 id。

factory-method 屬性:用于指定執行個體工廠中建立對象的方法。

<bean id="instanceFactory" class="com.wyj.factory.InstanceFactory"></bean>
<bean id="accountService" factory-bean="instanceFactory" factory-method="getAccountService"></bean>
           
public class InstanceFactory {
    public IAccountService getAccountService(){
        return new AccountServiceImpl();
    }
}
           

4.2 bean的作用範圍

bean作用:

用于配置對象讓 spring 來建立的。

預設情況下它調用的是類中的無參構造函數。如果沒有無參構造函數則不能建立成功。

屬性:

id:給對象在容器中提供一個唯一辨別。用于擷取對象。

class:指定類的全限定類名。用于反射建立對象。預設情況下調用無參構造函數。

scope:指定對象的作用範圍。

  • singleton :預設值,單例的.
  • prototype :多例的.
  • request :WEB 項目中,Spring 建立一個 Bean 的對象,将對象存入到 request 域中.
  • session :WEB 項目中,Spring 建立一個 Bean 的對象,将對象存入到 session 域中.
  • global session :WEB 項目中,應用在 Portlet 環境.如果沒有 Portlet 環境那麼

    globalSession 相當于 session.

  • init-method:指定類中的初始化方法名稱。
  • destroy-method:指定類中銷毀方法名稱。

4.3 bean的生命周期

單例對象:scope=“singleton”

一個應用隻有一個對象的執行個體。它的作用範圍就是整個應用。

生命周期:

對象出生:當應用加載,建立容器時,對象就被建立了。

對象活着:隻要容器在,對象一直活着。

對象死亡:當應用解除安裝,銷毀容器時,對象就被銷毀了。

多例對象:scope=“prototype”

每次通路對象時,都會重新建立對象執行個體。

生命周期:

對象出生:當使用對象時,建立新的對象執行個體。

對象活着:隻要對象在使用中,就一直活着。

對象死亡:當對象長時間不用時,被 java 的垃圾回收器回收了。

5. spring的依賴注入

5.1 依賴注入的概念

==依賴注入:Dependency Injection。==它是 spring 架構核心 ioc 的具體實作。我們的程式在編寫時,通過控制反轉,把對象的建立交給了 spring,但是代碼中不可能出現沒有依賴的情況。ioc 解耦隻是降低他們的依賴關系,但不會消除。例如:我們的業務層仍會調用持久層的方法。那這種業務層和持久層的依賴關系,在使用 spring 之後,就讓 spring 來維護了。簡單的說,就是坐等架構把持久層對象傳入業務層,而不用我們自己去擷取。

在目前類需要用到其他類的對象,由spring為我們提供,我們隻需要在配置檔案中說明,依賴關系的維護,就稱之為依賴注入。

依賴注入:

== 能注入的資料:==

基本類型和String

其他bean類型(在配置檔案中或者注解配置過的bean)

複雜類型/集合類型

== 注入的方式:==

使用構造方式提供

使用set方法提供

使用注解提供

5.2 構造函數注入

顧名思義,就是使用類中的構造函數,給成員變量指派。注意,指派的操作不是我們自己做的,而是通過配置的方式,讓 spring 架構來為我們注入。

public class AccountServiceImpl implements IAccountService {
    //如果是經常變化的資料,并不适用于注入的方式
    private String name;
    private Integer age;
    private Date birthday;
    public AccountServiceImpl(String name,Integer age,Date birthday){
        this.name=name;
        this.age=age;
        this.birthday=birthday;
    }
    public void saveAccount() {
        System.out.println("service中的saveAccount方法執行了。。。"+name+","+age+","+birthday);
    }
}
           

使用的标簽:constructor-age

标簽出現的位置:bean标簽的内部

标簽中的屬性:

type:用于指定要注入的資料類型,該資料類型也是構造函數中某個或某些參數的類型

index:用于指定要注入的資料給構造函數中指定索引位置的參數指派。索引位置從0開始。

name:用于指定給構造函數中指定名稱的參數指派(常用的)

--------------------------以上三個用于指定給構造函數中那個參數指派--------------------

value:用于提供基本類型和string類型的資料

ref:用于指定其他的bean類型的資料。它指的是在spring的ioc核心容器中出現過的bean對象

優點:在擷取bean對象時,注入資料是必須的操作,否則對象無法建立成功
    缺點:改變了bean對象的執行個體化方式,使我們在建立對象時如果用不到這些資料也必須提供
           
<bean id="accountService" class="com.wyj.service.impl.AccountServiceImpl">
        <constructor-arg name="name" value="test"></constructor-arg>
        <constructor-arg name="age" value="18"></constructor-arg>
        <constructor-arg name="birthday" ref="now"></constructor-arg>
    </bean>
    <!--配置一個日期對象-->
    <bean id="now" class="java.util.Date"></bean>
           

5.3 set 方法注入(常用)

public class AccountServiceImpl2 implements IAccountService {
    //如果是經常變化的資料,并不适用于注入的方式
    private String name;
    private Integer age;
    private Date birthday;
    public void setName(String name) {
        this.name = name;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }
    public void saveAccount() {
        System.out.println("service中的saveAccount方法執行了。。。"+name+","+age+","+birthday);
    }
}

           

涉及的标簽:property

出現的位置:bean标簽的内部

标簽的屬性:

name:用于指定注入時所調用的set方法名稱

value:用于提供基本類型和string類型的資料

ref:用于指定其他的bean類型的資料。它指的是在spring的ioc核心容器中出現過的bean對象

優點:建立對象時沒有明确的限制,可以直接使用預設構造函數
   缺點:如果有某個成員必須有值,則擷取對象是有可能set方法沒有執行
           
<bean id="accountService2" class="com.wyj.service.impl.AccountServiceImpl2">
        <property name="name" value="test"></property>
        <property name="age" value="21"></property>
        <property name="birthday" ref="now"></property>
    </bean>
    
           

5.4 注入集合資料

public class AccountServiceImpl3 implements IAccountService {
    private String[] myStr;
    private List<String> myList;
    private Set<String> mySet;
    private Map<String,String> myMap;
    private Properties myProps;
    public void setMyStr(String[] myStr) {
        this.myStr = myStr;
    }
    public void setMyList(List<String> myList) {
        this.myList = myList;
    }
    public void setMySet(Set<String> mySet) {
        this.mySet = mySet;
    }
    public void setMyMap(Map<String, String> myMap) {
        this.myMap = myMap;
    }
    public void setMyProps(Properties myProps) {
        this.myProps = myProps;
    }
    public void saveAccount() {
        System.out.println(Arrays.toString(myStr));
        System.out.println(myList);
        System.out.println(mySet);
        System.out.println(myMap);
        System.out.println(myProps);
    }
}
           

注入集合資料

List 結構的:

array,list,set

Map 結構的

map,entry,props,prop

<bean id="accountService3" class="com.wyj.service.impl.AccountServiceImpl3">
        <property name="myStr">
            <array>
                <value>AAA</value>
                <value>BBB</value>
                <value>CCC</value>
            </array>
        </property>

        <property name="myList">
            <list>
                <value>AAA</value>
                <value>BBB</value>
                <value>CCC</value>
            </list>
        </property>

        <property name="mySet">
            <set>
                <value>AAA</value>
                <value>BBB</value>
                <value>CCC</value>
            </set>
        </property>

        <property name="myMap">
            <map>
                <entry key="testA" value="aaa"></entry>
                <entry key="testB">
                    <value>bbb</value>
                </entry>
            </map>
        </property>

        <property name="myProps">
            <props>
                <prop key="testC">ccc</prop>
                <prop key="testD">ddd</prop>
            </props>
        </property>
    </bean>