黑馬 第一天:spring 框架的概述以及spring中基于XML的IOC配置

第1章 Spring 概述

1.1 spring 概述[了解]

1.1.1 spring 是什么

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

1.1.2 spring 的優(yōu)勢(shì)

方便解耦,簡(jiǎn)化開發(fā)
通過 Spring 提供的 IoC 容器,可以將對(duì)象間的依賴關(guān)系交由 Spring 進(jìn)行控制,避免硬編碼所造成的過度程序耦合。用戶也不必再為單例模式類盛杰、屬性文件解析等這些很底層的需求編寫代碼,可以更專注于上層的應(yīng)用存皂。

AOP 編程的支持
通過 Spring 的 AOP 功能,方便進(jìn)行面向切面的編程,許多不容易用傳統(tǒng) OOP 實(shí)現(xiàn)的功能可以通過 AOP 輕松應(yīng)付晨川。

聲明式事務(wù)的支持
可以將我們從單調(diào)煩悶的事務(wù)管理代碼中解脫出來,通過聲明式方式靈活的進(jìn)行事務(wù)的管理,提高開發(fā)效率和質(zhì)量。

方便程序的測(cè)試
可以用非容器依賴的編程方式進(jìn)行幾乎所有的測(cè)試工作,測(cè)試不再是昂貴的操作,而是隨手可做的事情椭微。

方便集成各種優(yōu)秀框架

? Spring 可以降低各種框架的使用難度,提供了對(duì)各種優(yōu)秀框架(Struts、 Hibernate蝇率、 Hessian、 Quartz等)的直接支持本慕。

降低 JavaEE API 的使用難度
Spring 對(duì) JavaEE API(如 JDBC排拷、JavaMail锅尘、遠(yuǎn)程調(diào)用等)進(jìn)行了薄薄的封裝層,使這些 API 的使用難度大為降低。

Java 源碼是經(jīng)典學(xué)習(xí)范例
Spring 的源代碼設(shè)計(jì)精妙藤违、結(jié)構(gòu)清晰纺弊、匠心獨(dú)用,處處體現(xiàn)著大師對(duì) Java 設(shè)計(jì)模式靈活運(yùn)用以及對(duì) Java 技術(shù)的高深造詣骡男。它的源代碼無意是 Java 技術(shù)的最佳實(shí)踐的范例。

第2章 IoC 的概念和作用

2.1 程序的耦合和解耦[理解]

2.1.1 什么是程序的耦合

? 耦合性(Coupling),也叫耦合度,是對(duì)模塊間關(guān)聯(lián)程度的度量犹菱。耦合的強(qiáng)弱取決于模塊間接口的復(fù)雜性吮炕、調(diào)用模塊的方式以及通過界面?zhèn)魉蛿?shù)據(jù)的多少。模塊間的耦合度是指模塊之間的依賴關(guān)系,包括控制關(guān)系陕凹、調(diào)用關(guān)系鳄炉、數(shù)據(jù)傳遞關(guān)系。模塊間聯(lián)系越多,其耦合性越強(qiáng),同時(shí)表明其獨(dú)立性越差 ( 降低耦合性,可以提高其獨(dú)立性)佑女。耦合性存在于各個(gè)領(lǐng)域,而非軟件設(shè)計(jì)中獨(dú)有的,但是我們只討論軟件工程中的耦合。

? 在軟件工程中,耦合指的就是就是對(duì)象之間的依賴性摸吠。對(duì)象之間的耦合越高,維護(hù)成本越高。因此對(duì)象的設(shè)計(jì)應(yīng)使類和構(gòu)件之間的耦合最小嚎花。軟件設(shè)計(jì)中通常用耦合度和內(nèi)聚度作為衡量模塊獨(dú)立程度的標(biāo)準(zhǔn)寸痢。劃分模塊的一個(gè)準(zhǔn)則就是高內(nèi)聚低耦合
它有如下分類:
(1) 內(nèi)容耦合紊选。當(dāng)一個(gè)模塊直接修改或操作另一個(gè)模塊的數(shù)據(jù)時(shí),或一個(gè)模塊不通過正常入口而轉(zhuǎn)入另一個(gè)模塊時(shí),這樣的耦合被稱為內(nèi)容耦合。內(nèi)容耦合是最高程度的耦合,應(yīng)該避免使用之族壳。
(2) 公共耦合趣些。兩個(gè)或兩個(gè)以上的模塊共同引用一個(gè)全局?jǐn)?shù)據(jù)項(xiàng),這種耦合被稱為公共耦合坏平。在具有大量公共耦合的結(jié)構(gòu)中,確定究竟是哪個(gè)模塊給全局變量賦了一個(gè)特定的值是十分困難的。
(3) 外部耦合 令境。一組模塊都訪問同一全局簡(jiǎn)單變量而不是同一全局?jǐn)?shù)據(jù)結(jié)構(gòu),而且不是通過參數(shù)表傳遞該全局變量的信息,則稱之為外部耦合顾瞪。
(4) 控制耦合 陈醒。一個(gè)模塊通過接口向另一個(gè)模塊傳遞一個(gè)控制信號(hào),接受信號(hào)的模塊根據(jù)信號(hào)值而進(jìn)行適當(dāng)?shù)膭?dòng)作,這種耦合被稱為控制耦合。
(5) 標(biāo)記耦合 弥鹦。若一個(gè)模塊 A 通過接口向兩個(gè)模塊 B 和 C 傳遞一個(gè)公共參數(shù),那么稱模塊 B 和 C 之間存在一個(gè)標(biāo)記耦合彬坏。
(6) 數(shù)據(jù)耦合膝晾。模塊之間通過參數(shù)來傳遞數(shù)據(jù),那么被稱為數(shù)據(jù)耦合玷犹。數(shù)據(jù)耦合是最低的一種耦合形式,系統(tǒng)中一般都存在這種類型的耦合,因?yàn)闉榱送瓿梢恍┯幸饬x的功能,往往需要將某些模塊的輸出數(shù)據(jù)作為另一些模塊的輸入數(shù)據(jù)洒疚。
(7) 非直接耦合 油湖。兩個(gè)模塊之間沒有直接關(guān)系,它們之間的聯(lián)系完全是通過主模塊的控制和調(diào)用來實(shí)現(xiàn)的领跛。
總結(jié):
耦合是影響軟件復(fù)雜程度和設(shè)計(jì)質(zhì)量的一個(gè)重要因素,在設(shè)計(jì)上我們應(yīng)采用以下原則:如果模塊間必須存在耦合,就盡量使用數(shù)據(jù)耦合,少用控制耦合,限制公共耦合的范圍,盡量避免使用內(nèi)容耦合吠昭。
內(nèi)聚與耦合
內(nèi)聚標(biāo)志一個(gè)模塊內(nèi)各個(gè)元素彼此結(jié)合的緊密程度,它是信息隱蔽和局部化概念的自然擴(kuò)展。內(nèi)聚是從功能角度來度量模塊內(nèi)的聯(lián)系,一個(gè)好的內(nèi)聚模塊應(yīng)當(dāng)恰好做一件事郑什。它描述的是模塊內(nèi)的功能聯(lián)系蒲肋。耦合是軟件結(jié)構(gòu)中各模塊之間相互連接的一種度量,耦合強(qiáng)弱取決于模塊間接口的復(fù)雜程度兜粘、進(jìn)入或訪問一個(gè)模塊的點(diǎn)以及通過接口的數(shù)據(jù)。 程序講究的是低耦合,高內(nèi)聚剃法。就是同一個(gè)模塊內(nèi)的各個(gè)元素之間要高度緊密,但是各個(gè)模塊之間的相互依存度卻要不那么緊密贷洲。
內(nèi)聚和耦合是密切相關(guān)的,同其他模塊存在高耦合的模塊意味著低內(nèi)聚,而高內(nèi)聚的模塊意味著該模塊同其他模塊之間是低耦合悍引。在進(jìn)行軟件設(shè)計(jì)時(shí),應(yīng)力爭(zhēng)做到高內(nèi)聚,低耦合趣斤。
我們?cè)陂_發(fā)中,有些依賴關(guān)系是必須的,有些依賴關(guān)系可以通過優(yōu)化代碼來解除的黎休。

    
        請(qǐng)看下面的示例代碼:
/**
 * 賬戶的業(yè)務(wù)層實(shí)現(xiàn)類
 * @author 黑馬程序員
 * @Company http://www.ithiema.com
 * @Version 1.0
 */
public class AccountServiceImpl implements IAccountService {
    private IAccountDao accountDao = new AccountDaoImpl();
}
上面的代碼表示:
    業(yè)務(wù)層調(diào)用持久層,并且此時(shí)業(yè)務(wù)層在依賴持久層的接口和實(shí)現(xiàn)類势腮。如果此時(shí)沒有持久層實(shí)現(xiàn)類,編譯將不能通過。這種編譯期依賴關(guān)系,應(yīng)該在我們開發(fā)中杜絕泪幌。我們需要優(yōu)化代碼解決祸泪。


再比如:
    早期我們的 JDBC 操作,注冊(cè)驅(qū)動(dòng)時(shí),我們?yōu)槭裁床皇褂?DriverManager 的 register 方法,而是采用Class.forName 的方式?
public class JdbcDemo1 {
    /**
     * @author 黑馬程序員
     * @Company http://www.ithiema.com
     * @Version 1.0
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        //1.注冊(cè)驅(qū)動(dòng)
        //DriverManager.registerDriver(new com.mysql.jdbc.Driver());
        Class.forName("com.mysql.jdbc.Driver");
        //2.獲取連接
        //3.獲取預(yù)處理 sql 語句對(duì)象
        //4.獲取結(jié)果集
        //5.遍歷結(jié)果集
    }
}
原因就是:
        我們的類依賴了數(shù)據(jù)庫的具體驅(qū)動(dòng)類(MySQL),如果這時(shí)候更換了數(shù)據(jù)庫品牌(比如 Oracle),需要修改源碼來重新數(shù)據(jù)庫驅(qū)動(dòng)。這顯然不是我們想要的懂扼。

2.1.2 解決程序耦合的思路

當(dāng)是我們講解 jdbc 時(shí),是通過反射來注冊(cè)驅(qū)動(dòng)的,代碼如下:
    Class.forName("com.mysql.jdbc.Driver");//此處只是一個(gè)字符串
    此時(shí)的好處是,我們的類中不再依賴具體的驅(qū)動(dòng)類,此時(shí)就算刪除 mysql 的驅(qū)動(dòng) jar 包,依然可以編譯(運(yùn)行就不要想了,沒有驅(qū)動(dòng)不可能運(yùn)行成功的)阀湿。
    同時(shí),也產(chǎn)生了一個(gè)新的問題,mysql 驅(qū)動(dòng)的全限定類名字符串是在 java 類中寫死的,一旦要改還是要修改源碼瑰妄。
    解決這個(gè)問題也很簡(jiǎn)單,使用配置文件配置间坐。

2.1.3 工廠模式解耦

? 在實(shí)際開發(fā)中我們可以把三層的對(duì)象都使用配置文件配置起來,當(dāng)啟動(dòng)服務(wù)器應(yīng)用加載的時(shí)候,讓一個(gè)類中的方法通過讀取配置文件,把這些對(duì)象創(chuàng)建出來并存起來。在接下來的使用的時(shí)候,直接拿過來用就好了涨醋。
那么,這個(gè)讀取配置文件,創(chuàng)建和獲取三層對(duì)象的類就是工廠逝撬。

2.1.4 控制反轉(zhuǎn)-Inversion Of Control

上一小節(jié)解耦的思路有 2 個(gè)問題:
1宪潮、存哪去?
分析:由于我們是很多對(duì)象,肯定要找個(gè)集合來存狡相。這時(shí)候有 Map 和 List 供選擇。
到底選 Map 還是 List 就看我們有沒有查找需求喳挑。有查找需求,選 Map滔悉。
所以我們的答案就是
在應(yīng)用加載時(shí),創(chuàng)建一個(gè) Map,用于存放三層對(duì)象回官。
我們把這個(gè) map 稱之為容器。

2笛坦、還是沒解釋什么是工廠?
工廠就是負(fù)責(zé)給我們從容器中獲取指定對(duì)象的類。這時(shí)候我們獲取對(duì)象的方式發(fā)生了改變蜗帜。
原來:
我們?cè)讷@取對(duì)象時(shí),都是采用 new 的方式厅缺。是主動(dòng)的宴偿。

image.png

現(xiàn)在:
    我們獲取對(duì)象時(shí),同時(shí)跟工廠要,有工廠為我們查找或者創(chuàng)建對(duì)象窄刘。是被動(dòng)的。
image.png

? 這種被動(dòng)接收的方式獲取對(duì)象的思想就是控制反轉(zhuǎn),它是 spring 框架的核心之一。
明確 ioc 的作用:
削減計(jì)算機(jī)程序的耦合(解除我們代碼中的依賴關(guān)系)翻伺。

第3章 使用 spring 的 IOC 解決程序耦合

3.1 案例的前期準(zhǔn)備[會(huì)用]

? 本章我們使用的案例是,賬戶的業(yè)務(wù)層和持久層的依賴關(guān)系解決吨岭。在開始 spring 的配置之前,我們要先準(zhǔn)備一下環(huán)境辣辫。由于我們是使用 spring 解決依賴關(guān)系,并不是真正的要做增刪改查操作,所以此時(shí)我們沒必要寫實(shí)體類。并且我們?cè)诖颂幨褂玫氖?java 工程,不是 java web 工程姐浮。

3.1.1 準(zhǔn)備 spring 的開發(fā)包

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.0.2.RELEASE</version>
    </dependency>
</dependencies>

3.1.2 創(chuàng)建業(yè)務(wù)層接口和實(shí)現(xiàn)類

/**
 * 賬戶的業(yè)務(wù)層接口
 * @author 黑馬程序員
 * @Company http://www.ithiema.com
 * @Version 1.0
 */
public interface IAccountService {
    /**
     * 保存賬戶(此處只是模擬,并不是真的要保存)
     */
    void saveAccount();
}
/**
 * 賬戶的業(yè)務(wù)層實(shí)現(xiàn)類
 * @author 黑馬程序員
 * @Company http://www.ithiema.com
 * @Version 1.0
 */
public class AccountServiceImpl implements IAccountService {
    private IAccountDao accountDao = new AccountDaoImpl();//此處的依賴關(guān)系有待解決
    @Override
    public void saveAccount() {
        accountDao.saveAccount();
    }
}

3.1.3 創(chuàng)建持久層接口和實(shí)現(xiàn)類

/**
 * 賬戶的持久層接口
 * @author 黑馬程序員
 * @Company http://www.ithiema.com
 * @Version 1.0
 */
public interface IAccountDao {
    /**
     * 保存賬戶
     */
    void saveAccount();
}
/**
 * 賬戶的持久層實(shí)現(xiàn)類
 * @author 黑馬程序員
 * @Company http://www.ithiema.com
 * @Version 1.0
 */
public class AccountDaoImpl implements IAccountDao {
    @Override
    public void saveAccount() {
        System.out.println("保存了賬戶");
    }
}

3.2 基于 XML 的配置(入門案例)[掌握]

3.2.1 第一步:拷貝必備的 jar 包到工程的 lib 目錄中

3.2.2 第二步:在類的根路徑下創(chuàng)建一個(gè)任意名稱的 xml 文件(不能是中文)

給配置文件導(dǎo)入約束:
/spring-framework-5.0.2.RELEASE/docs/spring-framework-reference/html5/core.html
<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>

3.2.3 第三步:讓 spring 管理資源,在配置文件中配置 service 和 dao

<!-- bean 標(biāo)簽:用于配置讓 spring 創(chuàng)建對(duì)象,并且存入 ioc 容器之中
        id 屬性:對(duì)象的唯一標(biāo)識(shí)。
        class 屬性:指定要?jiǎng)?chuàng)建對(duì)象的全限定類名
        -->
<!-- 配置 service -->
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
</bean>
<!-- 配置 dao -->
<bean id="accountDao" class="com.itheima.dao.impl.AccountDaoImpl"></bean>

3.2.4 測(cè)試配置是否成功

/**
 * 模擬一個(gè)表現(xiàn)層
 * @author 黑馬程序員
 * @Company http://www.ithiema.com
 * @Version 1.0
 */
public class Client {
    /**
     * 使用 main 方法獲取容器測(cè)試執(zhí)行
     */
    public static void main(String[] args) {
        //1.使用 ApplicationContext 接口,就是在獲取 spring 容器
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        //2.根據(jù) bean 的 id 獲取對(duì)象
        IAccountService aService = (IAccountService) ac.getBean("accountService");
        System.out.println(aService);
        IAccountDao aDao = (IAccountDao) ac.getBean("accountDao");
        System.out.println(aDao);
    }
}

3.3 Spring 基于 XML 的 IOC 細(xì)節(jié)[掌握]

3.3.1 spring 中工廠的類結(jié)構(gòu)圖

image.png

3.3.1.1 BeanFactory 和 ApplicationContext 的區(qū)別

BeanFactory 才是 Spring 容器中的頂層接口扫尖。
ApplicationContext 是它的子接口。
BeanFactoryApplicationContext 的區(qū)別:
創(chuàng)建對(duì)象的時(shí)間點(diǎn)不一樣蟀瞧。
ApplicationContext`:只要一讀取配置文件,默認(rèn)情況下就會(huì)創(chuàng)建對(duì)象。BeanFactory`:什么使用什么時(shí)候創(chuàng)建對(duì)象铸屉。

3.3.1.2 ApplicationContext 接口的實(shí)現(xiàn)類

ClassPathXmlApplicationContext:
它是從類的根路徑下加載配置文件 推薦使用這種
FileSystemXmlApplicationContext:
它是從磁盤路徑上加載配置文件,配置文件可以在磁盤的任意位置切端。
AnnotationConfigApplicationContext:
當(dāng)我們使用注解配置容器對(duì)象時(shí),需要使用此類來創(chuàng)建 spring 容器踏枣。它用來讀取注解。

3.3.2 IOC 中 bean 標(biāo)簽和管理對(duì)象細(xì)節(jié)

3.3.2.1 bean 標(biāo)簽

作用:
用于配置對(duì)象讓 spring 來創(chuàng)建的间驮。
默認(rèn)情況下它調(diào)用的是類中的無參構(gòu)造函數(shù)竞帽。如果沒有無參構(gòu)造函數(shù)則不能創(chuàng)建成功鸿捧。
屬性:
??id:給對(duì)象在容器中提供一個(gè)唯一標(biāo)識(shí)。用于獲取對(duì)象抱虐。
??class:指定類的全限定類名恳邀。用于反射創(chuàng)建對(duì)象灶轰。默認(rèn)情況下調(diào)用無參構(gòu)造函數(shù)笋颤。
??scope:指定對(duì)象的作用范圍。

????singleton :默認(rèn)值,單例的.

????prototype:多例的.

????request :WEB 項(xiàng)目中,Spring 創(chuàng)建一個(gè) Bean 的對(duì)象,將對(duì)象存入到 request 域中.

?????session:WEB 項(xiàng)目中,Spring 創(chuàng)建一個(gè) Bean 的對(duì)象,將對(duì)象存入到 session 域中.

????global session:WEB 項(xiàng)目中,應(yīng)用在 Portlet 環(huán)境.如果沒有 Portlet 環(huán)境那么globalSession 相當(dāng)于 session.
??init-method:指定類中的初始化方法名稱赋除。
??destroy-method:指定類中銷毀方法名稱非凌。

3.3.2.2 bean 的作用范圍和生命周期

單例對(duì)象:scope="singleton"
一個(gè)應(yīng)用只有一個(gè)對(duì)象的實(shí)例。它的作用范圍就是整個(gè)引用颁糟。

? 生命周期:
對(duì)象出生:當(dāng)應(yīng)用加載,創(chuàng)建容器時(shí),對(duì)象就被創(chuàng)建了。
對(duì)象活著:只要容器在,對(duì)象一直活著玖媚。
對(duì)象死亡:當(dāng)應(yīng)用卸載,銷毀容器時(shí),對(duì)象就被銷毀了今魔。

多例對(duì)象:scope="prototype"
每次訪問對(duì)象時(shí),都會(huì)重新創(chuàng)建對(duì)象實(shí)例障贸。

? 生命周期:
對(duì)象出生:當(dāng)使用對(duì)象時(shí),創(chuàng)建新的對(duì)象實(shí)例。
對(duì)象活著:只要對(duì)象在使用中,就一直活著问词。
對(duì)象死亡:當(dāng)對(duì)象長(zhǎng)時(shí)間不用時(shí),被 java 的垃圾回收器回收了激挪。

3.3.2.3 實(shí)例化 Bean 的三種方式

第一種方式:使用默認(rèn)無參構(gòu)造函數(shù)

<!--在默認(rèn)情況下:
    它會(huì)根據(jù)默認(rèn)無參構(gòu)造函數(shù)來創(chuàng)建類對(duì)象锋叨。如果 bean 中沒有默認(rèn)無參構(gòu)造函數(shù),將會(huì)創(chuàng)建失敗娃磺。
-->
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"/>

第二種方式:spring 管理靜態(tài)工廠-使用靜態(tài)工廠的方法創(chuàng)建對(duì)象

    /**
    * 模擬一個(gè)靜態(tài)工廠,創(chuàng)建業(yè)務(wù)層實(shí)現(xiàn)類
    */
    public class StaticFactory {
        public static IAccountService createAccountService(){
        return new AccountServiceImpl();
        }
    }
    <!-- 此種方式是:
    使用 StaticFactory 類中的靜態(tài)方法 createAccountService 創(chuàng)建對(duì)象,并存入 spring 容器
    id 屬性:指定 bean 的 id,用于從容器中獲取
    class 屬性:指定靜態(tài)工廠的全限定類名
    factory-method 屬性:指定生產(chǎn)對(duì)象的靜態(tài)方法
    -->
<bean id="accountService" class="com.itheima.factory.StaticFactory" 
    factory-method="createAccountService"></bean>

第三種方式:spring 管理實(shí)例工廠-使用實(shí)例工廠的方法創(chuàng)建對(duì)象

 /**
    * 模擬一個(gè)實(shí)例工廠,創(chuàng)建業(yè)務(wù)層實(shí)現(xiàn)類
    * 此工廠創(chuàng)建對(duì)象,必須現(xiàn)有工廠實(shí)例對(duì)象,再調(diào)用方法
    */
    public class InstanceFactory {
        public IAccountService createAccountService(){
            return new AccountServiceImpl();
        }
    }
    <!-- 此種方式是:
    先把工廠的創(chuàng)建交給 spring 來管理偷卧。
    然后在使用工廠的 bean 來調(diào)用里面的方法
    factory-bean 屬性:用于指定實(shí)例工廠 bean 的 id。
    factory-method 屬性:用于指定實(shí)例工廠中創(chuàng)建對(duì)象的方法坐求。
    -->
<bean id="instancFactory" class="com.itheima.factory.InstanceFactory"></bean>
<bean id="accountService" factory-bean="instancFactory"
    factory-method="createAccountService"></bean>

3.3.3 spring 的依賴注入

3.3.3.1 依賴注入的概念

? 依賴注入:Dependency Injection桥嗤。它是 spring 框架核心 ioc 的具體實(shí)現(xiàn)仔蝌。
我們的程序在編寫時(shí),通過控制反轉(zhuǎn),把對(duì)象的創(chuàng)建交給了 spring,但是代碼中不可能出現(xiàn)沒有依賴的情況敛惊。ioc 解耦只是降低他們的依賴關(guān)系,但不會(huì)消除。例如:我們的業(yè)務(wù)層仍會(huì)調(diào)用持久層的方法篓像。
那這種業(yè)務(wù)層和持久層的依賴關(guān)系,在使用 spring 之后,就讓 spring 來維護(hù)了皿伺。
簡(jiǎn)單的說,就是坐等框架把持久層對(duì)象傳入業(yè)務(wù)層,而不用我們自己去獲取鸵鸥。

3.3.3.2 構(gòu)造函數(shù)注入

? 顧名思義,就是使用類中的構(gòu)造函數(shù),給成員變量賦值。注意,賦值的操作不是我們自己做的,而是通過配置的方式,讓 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;
    }
    @Override
    public void saveAccount() {
        System.out.println(name+","+age+","+birthday);
    }
}
 <!-- 使用構(gòu)造函數(shù)的方式,給 service 中的屬性傳值
        要求:
            類中需要提供一個(gè)對(duì)應(yīng)參數(shù)列表的構(gòu)造函數(shù)杰赛。
        涉及的標(biāo)簽:
            constructor-arg
        屬性:
            index:指定參數(shù)在構(gòu)造函數(shù)參數(shù)列表的索引位置
            type:指定參數(shù)在構(gòu)造函數(shù)中的數(shù)據(jù)類型    用這個(gè)找給誰賦值
            name:指定參數(shù)在構(gòu)造函數(shù)中的名稱
        =======上面三個(gè)都是找給誰賦值,下面兩個(gè)指的是賦什么值的==============
            value:它能賦的值是基本數(shù)據(jù)類型和 String 類型
            ref:它能賦的值是其他 bean 類型,也就是說,必須得是在配置文件中配置過的 bean
        -->
<bean id="accountService" class="com.itheima.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>

3.3.3.3 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 方法的方式
      涉及的標(biāo)簽:
        property
      屬性:
        name:找的是類中 set 方法后面的部分
        ref:給屬性賦值是其他 bean 類型的
        value:給屬性賦值是基本數(shù)據(jù)類型和 string 類型的
        實(shí)際開發(fā)中,此種方式用的較多辰晕。
        -->
<bean id="accountService" class="com.itheima.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>

3.3.3.4 使用 p 名稱空間注入數(shù)據(jù)(本質(zhì)還是調(diào)用 set 方法)

? 此種方式是通過在 xml 中導(dǎo)入 p 名稱空間,使用 p:propertyName 來注入數(shù)據(jù),它的本質(zhì)仍然是調(diào)用類中的set 方法實(shí)現(xiàn)注入功能含友。

public class AccountServiceImpl4 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);
    }
}
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:p="http://www.springframework.org/schema/p"
       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 id="accountService"
      class="com.itheima.service.impl.AccountServiceImpl4"
      p:name="test" p:age="21" p:birthday-ref="now"/>
</beans>

3.3.3.5 注入集合屬性

? 顧名思義,就是給類中的集合成員傳值,它用的也是 set 方法注入的方式,只不過變量的數(shù)據(jù)類型都是集合窘问。我們這里介紹注入數(shù)組,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);
    }
}
<!-- 注入集合數(shù)據(jù)
        List 結(jié)構(gòu)的:
        array,list,set
        Map 結(jié)構(gòu)的
        map,entry,props,prop
-->
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl">
<!-- 在注入集合數(shù)據(jù)時(shí),只要結(jié)構(gòu)相同,標(biāo)簽可以互換 -->
<!-- 給數(shù)組注入數(shù)據(jù) -->
<property name="myStrs">
    <set>
        <value>AAA</value>
        <value>BBB</value>
        <value>CCC</value>
    </set>
</property>
<!-- 注入 list 集合數(shù)據(jù) -->
<property name="myList">
    <array>
        <value>AAA</value>
        <value>BBB</value>
        <value>CCC</value>
    </array>
</property>
<!-- 注入 set 集合數(shù)據(jù) -->
<property name="mySet">
    <list>
        <value>AAA</value>
        <value>BBB</value>
        <value>CCC</value>
    </list>
</property>
<!-- 注入 Map 數(shù)據(jù) -->
<property name="myMap">
    <props>
        <prop key="testA">aaa</prop>
        <prop key="testB">bbb</prop>
    </props>
</property>
<!-- 注入 properties 數(shù)據(jù) -->
<property name="myProps">
    <map>
        <entry key="testA" value="aaa"></entry>
        <entry key="testB">
            <value>bbb</value>
        </entry>
    </map>
</property>
</bean>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市倍阐,隨后出現(xiàn)的幾起案子峰搪,更是在濱河造成了極大的恐慌,老刑警劉巖使套,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件侦高,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡奉呛,警方通過查閱死者的電腦和手機(jī)瞧壮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門咆槽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人麦射,你說我怎么就攤上這事小渊。” “怎么了半等?”我有些...
    開封第一講書人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵杀饵,是天一觀的道長(zhǎng)谬擦。 經(jīng)常有香客問我惨远,道長(zhǎng),這世上最難降的妖魔是什么葡幸? 我笑而不...
    開封第一講書人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任蔚叨,我火速辦了婚禮,結(jié)果婚禮上邢锯,老公的妹妹穿的比我還像新娘搀别。我一直安慰自己,他們只是感情好鸥鹉,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著单刁,像睡著了一般府适。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上逻淌,一...
    開封第一講書人閱讀 49,166評(píng)論 1 284
  • 那天卡儒,我揣著相機(jī)與錄音俐巴,去河邊找鬼欣舵。 笑死,一個(gè)胖子當(dāng)著我的面吹牛劣光,可吹牛的內(nèi)容都是我干的糟把。 我是一名探鬼主播,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了狭归?” 一聲冷哼從身側(cè)響起文判,我...
    開封第一講書人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤戏仓,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后敷待,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體榜揖,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡举哟,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年迅矛,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片壶硅。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡森瘪,死狀恐怖票堵,靈堂內(nèi)的尸體忽然破棺而出悴势,到底是詐尸還是另有隱情,我是刑警寧澤军俊,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布粪躬,位于F島的核電站,受9級(jí)特大地震影響提前,放射性物質(zhì)發(fā)生泄漏泳唠。R本人自食惡果不足惜狈网,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望笨腥。 院中可真熱鬧拓哺,春花似錦、人聲如沸脖母。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽镶奉。三九已至础淤,卻和暖如春哨苛,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背币砂。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來泰國打工建峭, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人决摧。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓亿蒸,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國和親掌桩。 傳聞我的和親對(duì)象是個(gè)殘疾皇子边锁,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

推薦閱讀更多精彩內(nèi)容