spring介紹和基於xml配置使用1

spring介紹和優勢

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

  • spring 的優勢:
    • 方便解耦,簡化開發
      通過 Spring提供的 IoC容器,可以將對象間的依賴關係交由 Spring進行控制,避免硬編碼所造成的過度程序耦合。用戶也不必再爲單例模式類、屬性文件解析等這些很底層的需求編寫代碼,可以更專注於上層的應用
    • AOP編程的支持
      • 通過 Spring的 AOP 功能,方便進行面向切面的編程,許多不容易用傳統OOP 實現的功能可以通過 AOP 輕鬆應付
    • 聲明式事務的支持
      可以將我們從單調煩悶的事務管理代碼中解脫出來,通過聲明式方式靈活的進行事務的管理,
      提高開發效率和質量
    • 方便程序的測試
      可以用非容器依賴的編程方式進行幾乎所有的測試工作,測試不再是昂貴的操作,而是隨手可
      做的事情
    • 方便集成各種優秀框架
      Spring可以降低各種框架的使用難度,提供了對各種優秀框架(Struts、Hibernate、Hessian、Quartz等)的直接支持
    • 降低 JavaEE API 的使用難度
      Spring對 JavaEE API(如 JDBC、JavaMail、遠程調用等)進行了薄薄的封裝層,使這些 API 的
      使用難度大爲降低
    • Java 源碼是經典學習範例
      Spring的源代碼設計精妙、結構清晰、匠心獨用,處處體現着大師對Java 設計模式靈活運用以
      及對 Java技術的高深造詣。它的源代碼無意是 Java 技術的最佳實踐的範例

spring體系結構

在這裏插入圖片描述

控制反轉(IOC)

在這裏插入圖片描述

工廠模式解耦:在實際開發中我們可以把三層的對象都使用配置文件配置起來,當啓動服務器應用加載的時候,讓一個類中的
方法通過讀取配置文件,把這些對象創建出來 並存起來。在接下來的使用的時候,直接拿過來用就好了。那麼,這個讀取配置文件,創建和獲取三層對象的類就是工廠

spring的控制反轉(IOC)
由於我們是很多對象,肯定要找個集合來存。這時候有 Map 和 List 供選擇。因爲有查找需求,所以選 Map,在應用加載時,創建一個 Map,用於存放三層對象。我們把這個 map 稱之爲 容器

工廠:工廠就是負責給我們從容器中獲取指定對象的類。這時候我們獲取對象的方式發生了改變

原來獲取對象:
我們在獲取對象時,都是採用 new 的方式。是主動的。如下圖
在這裏插入圖片描述
現在獲取對象:
我們獲取對象時,同時跟工廠要,有工廠爲我們查找或者創建對象。是被動的,如下圖,這種被動接收的方式獲取對象的思想就是控制反轉,它是 spring 框架的核心之一
在這裏插入圖片描述

使用spring的IOC解決程序耦合(xml方式)

  1. 準備 spring 的開發包
    • 官網:http://spring.io/
    • 下載地址:http://repo.springsource.org/libs-release-local/org/springframework/spring
      特別說明:
      我們使用的版本是 是 spring5.0.2,spring5 版本是用 jdk8 編寫的,所以要求我們的 jdk 版本是 8 及以上時 同時 tomcat 的版本要求 8.5 及以上
    • 解壓:(Spring 目錄結構:)
      docs :API 和開發規範
      libs :jar 包和源碼.
      schema :約束.
  2. 創建業務層接口和實現類
package com.company.dao;

/**
 * 賬戶的持久層接口
 */
public interface IAccountDao {

    /**
     * 模擬保存賬戶
     */
    void saveAccount();
}

package com.company.dao.impl;


import com.company.dao.IAccountDao;

/**
 * 賬戶的持久層實現類
 */
public class AccountDaoImpl implements IAccountDao {

    public  void saveAccount(){

        System.out.println("保存了賬戶");
    }
}

  1. 創建持久層接口和實現類
package com.company.service;

/**
 * 賬戶業務層的接口
 */
public interface IAccountService {

    /**
     * 模擬保存賬戶
     */
    void saveAccount();
}

package com.company.service.impl;

import com.company.dao.IAccountDao;
import com.company.service.IAccountService;

/**
 * 賬戶的業務層實現類
 */
public class AccountServiceImpl implements IAccountService {

    private IAccountDao accountDao ;

    public AccountServiceImpl(){
        System.out.println("對象創建了");
    }

    public void  saveAccount(){
        accountDao.saveAccount();
    }
}

  1. **拷貝必備的 jar 包到工程的 lib 目錄中,並在類的根路徑下創建的 一個任意名稱的 xml 文件,在xml中導入約束 **
    在這裏插入圖片描述
    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">
</beans>
  1. 讓 spring管理資源 ,在配置文件中配置 service 和dao
<?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 標籤:用於配置讓 spring 創建對象,並且存入 ioc 容器之中
        id 屬性:對象的唯一標識。
        class 屬性:指定要創建對象的全限定類名
	-->
    <!-- 配置 service -->
    <bean id="accountService" class="com.company.service.impl.AccountServiceImpl"></bean>
    <!-- 配置 dao -->
    <bean id="accountDao" class="com.company.dao.impl.AccountDaoImpl"></bean>

</beans>


  1. 測試 配置是否成功
package com.company.ui;

import com.company.dao.IAccountDao;
import com.company.service.IAccountService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Client {
    public static void main(String[] args) {
        //1.使用 ApplicationContext 接口,就是在獲取 spring 容器
        ApplicationContext applicationContext= new ClassPathXmlApplicationContext("bean.xml");
        //2.根據 bean 的 id 獲取對象
        IAccountService iAccountService = (IAccountService) applicationContext.getBean("accountService");
        System.out.println(iAccountService);
        IAccountDao iAccountDao = (IAccountDao) applicationContext.getBean("accountDao");
        System.out.println(iAccountDao);
    }

}

在這裏插入圖片描述

spring 中工廠的類結構圖

在這裏插入圖片描述

  • BeanFactory 和 和 ApplicationContext 的區別
BeanFactory 纔是 Spring 容器中的頂層接口。
ApplicationContext 是它的子接口。
BeanFactory 和 ApplicationContext 的區別:
創建對象的時間點不一樣。
ApplicationContext:只要一讀取配置文件,默認情況下就會創建對象。
BeanFactory:什麼使用什麼時候創建對象
  • ApplicationContext 接口
ClassPathXmlApplicationContext :
它是從類的根路徑下加載配置文件 推薦使用這種
FileSystemXmlApplicationContext :
它是從磁盤路徑上加載配置文件,配置文件可以在磁盤的任意位置。
AnnotationConfigApplicationContext:
當我們使用註解配置容器對象時,需要使用此類來創建 spring 容器。它用來讀取註解
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:指定類中銷燬方法名稱
bean 的作用範圍和生命週期
單例對象:scope="singleton"
一個應用只有一個對象的實例。它的作用範圍就是整個引用。
生命週期:
對象出生:當應用加載,創建容器時,對象就被創建了。
對象活着:只要容器在,對象一直活着。
對象死亡:當應用卸載,銷燬容器時,對象就被銷燬了。
多例對象:scope="prototype"
每次訪問對象時,都會重新創建對象實例。
生命週期:
對象出生:當使用對象時,創建新的對象實例。
對象活着:只要對象在使用中,就一直活着。
對象死亡:當對象長時間不用時,被 java 的垃圾回收器回收了
實例化 Bean 的三種方式
第一種方式:使用默認無參構造函數
<!--在默認情況下:
它會根據默認無參構造函數來創建類對象。如果 bean 中沒有默認無參構造函數,將會創建失敗-->
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"/>
第二種方式:spring 管理靜態工廠- 使用靜態工廠的方法創建對象
/**
* 模擬一個靜態工廠,創建業務層實現類
*/
public class StaticFactory {
public static IAccountService createAccountService(){
return new AccountServiceImpl();
}
}
<!-- 此種方式是:
使用 StaticFactory 類中的靜態方法 createAccountService 創建對象,並存入 spring 容器
id 屬性:指定 bean 的 id,用於從容器中獲取
class 屬性:指定靜態工廠的全限定類名
factory-method 屬性:指定生產對象的靜態方法
-->
<bean id="accountService"
class="com.itheima.factory.StaticFactory"
factory-method="createAccountService"></bean>
第三種方式:spring 管理實例工廠- 使用實例工廠的方法創建對象
/**
* 模擬一個實例工廠,創建業務層實現類
* 此工廠創建對象,必須現有工廠實例對象,再調用方法
*/
public class InstanceFactory {
public IAccountService createAccountService(){
return new AccountServiceImpl();
}
}
<!-- 此種方式是:
先把工廠的創建交給 spring 來管理。
然後在使用工廠的 bean 來調用裏面的方法
factory-bean 屬性:用於指定實例工廠 bean 的 id。
factory-method 屬性:用於指定實例工廠中創建對象的方法。
-->
<bean id="instancFactory" class="com.itheima.factory.InstanceFactory"></bean>
<bean id="accountService"
factory-bean="instancFactory"
factory-method="createAccountService"></bean>

spring 的依賴注入

  • 構造函數注入
顧名思義,就是使用類中的構造函數,給成員變量賦值。注意,賦值的操作不是我們自己做的,而是通過配置
的方式,讓 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);
    }
}

<!-- 使用構造函數的方式,給 service 中的屬性傳值
要求:
類中需要提供一個對應參數列表的構造函數。
涉及的標籤:
constructor-arg
屬性:
	index:指定參數在構造函數參數列表的索引位置
	type:指定參數在構造函數中的數據類型
	name:指定參數在構造函數中的名稱 用這個找給誰賦值
=======上面三個都是找給誰賦值,下面兩個指的是賦什麼值的==============
	value:它能賦的值是基本數據類型和 String 類型
	ref:它能賦的值是其他 bean 類型,也就是說,必須得是在配置文件中配置過的 bean
	優勢:
            在獲取bean對象時,注入數據是必須的操作,否則對象無法創建成功。
    弊端:
            改變了bean對象的實例化方式,使我們在創建對象時,如果用不到這些數據,也必須提供。
-->
<bean id="accountService" class="com.company.service.impl.AccountServiceImpl">
<constructor-arg name="name" value=" 張三 "></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>
  • set 方法注入,實際開發中,此種方式用的較多
//顧名思義,就是在類中提供需要注入成員的 set 方法。具體代碼如下:
public class AccountServiceImpl 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;
    }
    @Override
    public void saveAccount() {
        System.out.println(name+","+age+","+birthday);
    }
}

<!-- 通過配置文件給 bean 中的屬性傳值:使用 set 方法的方式
涉及的標籤:
property
屬性:
	name:找的是類中 set 方法後面的部分
	ref:給屬性賦值是其他 bean 類型的
	value:給屬性賦值是基本數據類型和 string 類型的
	實際開發中,此種方式用的較多。
	 優勢:
            創建對象時沒有明確的限制,可以直接使用默認構造函數
     弊端:
            如果有某個成員必須有值,則獲取對象是有可能set方法沒有執行。
-->
<bean id="accountService" class="com.company.service.impl.AccountServiceImpl">
<property name="name" value="test"></property>
<property name="age" value="21"></property>
<property name="birthday" ref="now"></property>
</bean>
<bean id="now" class="java.util.Date"></bean>

  • 注入集合屬性
顧名思義,就是給類中的集合成員傳值,它用的也是set方法注入的方式,只不過變量的數據類型都是集合。
我們這裏介紹注入數組,List,Set,Map,Properties。具體代碼如下:

public class AccountServiceImpl implements IAccountService {
    private String[] myStrs;
    private List<String> myList;
    private Set<String> mySet;
    private Map<String,String> myMap;
    private Properties myProps;
    public void setMyStrs(String[] myStrs) {
        this.myStrs = myStrs;
    }
    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;
    }
    @Override
    public void saveAccount() {
        System.out.println(Arrays.toString(myStrs));
        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="accountService" class="com.company.service.impl.AccountServiceImpl">
        <!-- 在注入集合數據時,只要結構相同,標籤可以互換 -->
        <!-- 給數組注入數據 -->
        <property name="myStrs">
            <set>
                <value>AAA</value>
                <value>BBB</value>
                <value>CCC</value>
            </set>
        </property>
        <!-- 注入 list 集合數據 -->
        <property name="myList">
            <array>
                <value>AAA</value>
                <value>BBB</value>
                <value>CCC</value>
            </array>
        </property>
        <!-- 注入 set 集合數據 -->
        <property name="mySet">
            <list>
                <value>AAA</value>
                <value>BBB</value>
                <value>CCC</value>
            </list>
        </property>
        <!-- 注入 Map 數據 -->
        <property name="myMap">
            <props>
                <prop key="testA">aaa</prop>
                <prop key="testB">bbb</prop>
            </props>
        </property>
        <!-- 注入 properties 數據 -->
        <property name="myProps">
            <map>
                <entry key="testA" value="aaa"></entry>
                <entry key="testB">
                    <value>bbb</value>
                </entry>
            </map>
        </property>
    </bean>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章