03 Spring IoC之對(duì)象間的相互關(guān)系和 Spring 應(yīng)用結(jié)構(gòu)

轉(zhuǎn)載請(qǐng)注明來(lái)源 賴賴的博客

導(dǎo)語(yǔ)

你知道的越多援雇,越容易接受新的知識(shí)吮铭。

Spring IoC是有應(yīng)用場(chǎng)景的时迫,其特定決定了應(yīng)用的結(jié)構(gòu);也就是說(shuō)谓晌,一旦你用了Spring掠拳,也就受到了框架的限制,只能使用一些特定的設(shè)計(jì)模式纸肉。

實(shí)例

項(xiàng)目工程目錄結(jié)構(gòu)和代碼獲取地址

獲取地址(版本Log將會(huì)注明每一個(gè)版本對(duì)應(yīng)的課程)

https://github.com/laiyijie/SpringLearning

目錄結(jié)構(gòu)

目錄結(jié)構(gòu)

乍一看溺欧,工程似乎打出上一次不少,多了好多柏肪;然而程序員做事姐刁,向來(lái)不會(huì)毫無(wú)章法,自有其中的規(guī)律烦味,而其中的規(guī)律了解了聂使,文件再多,也只是重復(fù)的工作量谬俄;

這個(gè)所謂的章法柏靶,就是今天要說(shuō)的重點(diǎn)之一,應(yīng)用的分層溃论;

Spring應(yīng)用結(jié)構(gòu)

現(xiàn)在工程有三個(gè)包屎蜓,包之間的關(guān)系如下:

  • 應(yīng)用層:me.laiyijie.demo , 只調(diào)用服務(wù)層
  • 服務(wù)層:me.laiyijie.demo.service,只調(diào)用數(shù)據(jù)層
  • 數(shù)據(jù)層:me.laiyijie.demo.dataaccess钥勋,最底層梆靖,直接操作持久化數(shù)據(jù)(文件控汉、數(shù)據(jù)庫(kù)等)

具體含義如下:

me.laiyijie.demo

最上層的應(yīng)用層

  • 向上:對(duì)應(yīng)的是整個(gè)應(yīng)用的出入口,現(xiàn)在的表現(xiàn)就是返吻,可以打印到控制臺(tái)姑子!
  • 向下只調(diào)用了me.laiyijie.demo.service,也就是說(shuō)Service層對(duì)這一層提供了服務(wù)测僵!
  • 職責(zé):負(fù)責(zé)處理入口數(shù)據(jù)和出口數(shù)據(jù)(如輸出輸入的格式化等)

me.laiyijie.demo.service

業(yè)務(wù)邏輯層街佑,所有的業(yè)務(wù)邏輯應(yīng)該在這一層實(shí)現(xiàn);

  • 向上: 向應(yīng)用層提供服務(wù)捍靠,也就是提供接口給me.laiyijie.demo這一層的函數(shù)調(diào)用
  • 向下只調(diào)用了me.laiyijie.demo.dataaccess
  • 職責(zé):通過(guò)調(diào)用dataaccess層實(shí)現(xiàn)業(yè)務(wù)邏輯沐旨,并且向應(yīng)用層提供服務(wù)。

me.laiyijie.demo.dataaccess

數(shù)據(jù)連接層榨婆,屏蔽底層于文件磁携、數(shù)據(jù)庫(kù)等持久化操作;

  • 向上:向service層提供服務(wù)良风,使得服務(wù)層無(wú)需直接操作文件等持久化數(shù)據(jù)
  • 向下: SQL谊迄,文件讀寫的
  • 職責(zé):通過(guò)調(diào)用JDBC等直接操作數(shù)據(jù)庫(kù)和文件等持久化數(shù)據(jù)

小結(jié)

分層滿足兩個(gè)原則:

  1. 各層職責(zé)明確
  2. 僅調(diào)用自己的下一層,不會(huì)越層調(diào)用

運(yùn)行工程

運(yùn)行具有Main函數(shù)的 App.java
得到如下輸出

false

詳細(xì)解讀

程序入口為App.java從這里入口讀代碼

App.java

package me.laiyijie.demo;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import me.laiyijie.demo.service.UserService;

public class App {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("root-context.xml");
        
        UserService userService = context.getBean(UserService.class);
        
        System.out.println(userService.login("lailai", "laiyijie","127.0.0.1"));
        
        context.close();
    }
}

Main函數(shù)中依舊只有四行代碼烟央,這里引用到了UserService统诺,并且調(diào)用了UserServicelogin方法。

我們來(lái)看下UserService

UserService.java

package me.laiyijie.demo.service;

public interface UserService{
    
    boolean login(String username,String password,String ip);
    
}

OK疑俭,非常簡(jiǎn)單粮呢,只是一個(gè)接口,定義了有這么一個(gè)方法钞艇,具體實(shí)現(xiàn)是在同一個(gè)包下面的另一個(gè)文件啄寡,UserServiceImpl.java中

UserServiceImpl.java

package me.laiyijie.demo.service;

import me.laiyijie.demo.dataaccess.AccountAccess;
import me.laiyijie.demo.dataaccess.LoginLogAccess;

public class UserServiceImpl implements UserService {

    private AccountAccess accountAccess;
    
    private LoginLogAccess loginLogAccess;
    
    public boolean login(String username, String password,String ip) {
        
        if (!accountAccess.isAccountExist(username)) {
            return false;
        }
        
        if (accountAccess.isPasswordRight(username, password)) {
            accountAccess.updateLastLoginTime(username);
            loginLogAccess.addLoginLog(username, ip);
            return true;
        }
        return false;
    }

    public AccountAccess getAccountAccess() {
        return accountAccess;
    }

    public void setAccountAccess(AccountAccess accountAccess) {
        this.accountAccess = accountAccess;
    }

    public LoginLogAccess getLoginLogAccess() {
        return loginLogAccess;
    }

    public void setLoginLogAccess(LoginLogAccess loginLogAccess) {
        this.loginLogAccess = loginLogAccess;
    }
}

乍一看這個(gè)代碼,好長(zhǎng)哩照,函數(shù)好多挺物。其實(shí)并不復(fù)雜,
如果你對(duì)Java有一些了解的話應(yīng)該知道葡秒,后面的四個(gè)函數(shù)是getter和setter函數(shù),是向外提供了操作私有變量的方法嵌溢;
而最前面一個(gè)函數(shù)正是實(shí)現(xiàn)了UserService這個(gè)接口眯牧。

在這個(gè)類中,我們可以看到赖草,其通過(guò)私有變量的方式引用了dataaccess層的兩個(gè)對(duì)象学少!

private AccountAccess accountAccess;

private LoginLogAccess loginLogAccess;

那么,在沒(méi)有使用Spring的情況下秧骑,我們的main函數(shù)應(yīng)該這樣調(diào)用login方法:

public static void main(String[] args) {

    AccountAccess accountAccess = new AccountAccessImpl();
    LoginLogAccess loginLogAccess = new LoginLogAccessImpl();
    
    UserServiceImpl userServiceImpl = new UserServiceImpl();
    userServiceImpl.setAccountAccess(accountAccess);
    userServiceImpl.setLoginLogAccess(loginLogAccess);
    
    userServiceImpl.login("lailai", "laiyijie", "127.0.0.1");
}

然而在App.java中版确,我們直接

UserService userService = context.getBean(UserService.class);
        
System.out.println(userService.login("lailai", "laiyijie","127.0.0.1"));

也就是說(shuō)扣囊,對(duì)象創(chuàng)建,以及對(duì)象之間的依賴關(guān)聯(lián)通過(guò)root-context.xml來(lái)完成绒疗!

root-context.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: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/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">

    <bean id="accountAccessImpl" class="me.laiyijie.demo.dataaccess.AccountAccessImpl" ></bean>
    <bean id="loginLogAccessImpl" class="me.laiyijie.demo.dataaccess.LoginLogAccessImpl"></bean>
    
    <bean class="me.laiyijie.demo.service.UserServiceImpl">
        <property ref="accountAccessImpl" name="accountAccess"></property>
        <property ref="loginLogAccessImpl" name="loginLogAccess"></property>
    </bean>

</beans>

經(jīng)過(guò)前兩節(jié)課的基礎(chǔ)侵歇,你應(yīng)該可以輕易看懂這些配置,無(wú)非就是完成了對(duì)象的創(chuàng)建和屬性的設(shè)置操作吓蘑;也就是與這段代碼的功能一樣:

    AccountAccess accountAccess = new AccountAccessImpl();
    LoginLogAccess loginLogAccess = new LoginLogAccessImpl();
    
    UserServiceImpl userServiceImpl = new UserServiceImpl();
    userServiceImpl.setAccountAccess(accountAccess);
    userServiceImpl.setLoginLogAccess(loginLogAccess);

而這種配置方法惕虑,也就被稱為屬性注入

小結(jié)

  • 屬性注入就是通過(guò)Spring的配置文件可以完成對(duì)對(duì)象屬性的配置,從而使得不從層次的對(duì)象之間產(chǎn)生依賴關(guān)系磨镶,換句話講溃蔫,就是

    屬性注入提供了層與層之間的調(diào)用方式

  • 然而恰恰就是這種依賴注入的方式,使得層次的劃分是水平劃分琳猫,是一層一層的向上提供服務(wù)伟叛!
  • Spring提供的注入方式還有一種就是構(gòu)造注入,也就是在構(gòu)造方法的時(shí)候注入屬性脐嫂,如果理解了屬性注入想必不難理解構(gòu)造注入统刮。此處不展開,因?yàn)閷傩宰⑷肟梢詽M足絕大部分的應(yīng)用場(chǎng)景

附:

dataaccess層均為模擬雹锣,未實(shí)際接入持久層网沾,待后續(xù)添加。

AccountAccess.java

package me.laiyijie.demo.dataaccess;

public interface AccountAccess {
    
    boolean isAccountExist(String username);

    boolean isPasswordRight(String username, String password);
    
    void updateLastLoginTime(String username);
}

AccountAccessImpl.java

package me.laiyijie.demo.dataaccess;

public class AccountAccessImpl implements AccountAccess {

    public boolean isAccountExist(String username) {
        
        if ("laiyijie".equals(username)) {
            return true;
        }
        return false;
    }

    public void updateLastLoginTime(String username) {

    }

    public boolean isPasswordRight(String username, String password) {
        
        if ("laiyijie".equals(username)&&"123456".equals(password)) {
            return true;
        }
        return false;
    }

}

LoginLogAccess.java

package me.laiyijie.demo.dataaccess;

public interface LoginLogAccess {
    void addLoginLog(String username,String ip);
}

LoginLogAccessImpl.java

package me.laiyijie.demo.dataaccess;

public class LoginLogAccessImpl implements LoginLogAccess {

    public void addLoginLog(String username, String ip) {

    }
}

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>me.laiyijie</groupId>
    <artifactId>demo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <dependencies>

        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.3.2.RELEASE</version>
        </dependency>

    </dependencies>
</project>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末蕊爵,一起剝皮案震驚了整個(gè)濱河市辉哥,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌攒射,老刑警劉巖醋旦,帶你破解...
    沈念sama閱讀 217,826評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異会放,居然都是意外死亡饲齐,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門咧最,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)捂人,“玉大人,你說(shuō)我怎么就攤上這事矢沿±拇睿” “怎么了?”我有些...
    開封第一講書人閱讀 164,234評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵捣鲸,是天一觀的道長(zhǎng)瑟匆。 經(jīng)常有香客問(wèn)我,道長(zhǎng)栽惶,這世上最難降的妖魔是什么愁溜? 我笑而不...
    開封第一講書人閱讀 58,562評(píng)論 1 293
  • 正文 為了忘掉前任疾嗅,我火速辦了婚禮,結(jié)果婚禮上冕象,老公的妹妹穿的比我還像新娘代承。我一直安慰自己,他們只是感情好交惯,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評(píng)論 6 392
  • 文/花漫 我一把揭開白布次泽。 她就那樣靜靜地躺著,像睡著了一般席爽。 火紅的嫁衣襯著肌膚如雪意荤。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,482評(píng)論 1 302
  • 那天只锻,我揣著相機(jī)與錄音玖像,去河邊找鬼。 笑死齐饮,一個(gè)胖子當(dāng)著我的面吹牛捐寥,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播祖驱,決...
    沈念sama閱讀 40,271評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼握恳,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了捺僻?” 一聲冷哼從身側(cè)響起乡洼,我...
    開封第一講書人閱讀 39,166評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎匕坯,沒(méi)想到半個(gè)月后束昵,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,608評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡葛峻,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評(píng)論 3 336
  • 正文 我和宋清朗相戀三年锹雏,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片术奖。...
    茶點(diǎn)故事閱讀 39,926評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡礁遵,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出采记,到底是詐尸還是另有隱情佣耐,我是刑警寧澤,帶...
    沈念sama閱讀 35,644評(píng)論 5 346
  • 正文 年R本政府宣布挺庞,位于F島的核電站晰赞,受9級(jí)特大地震影響稼病,放射性物質(zhì)發(fā)生泄漏选侨。R本人自食惡果不足惜掖鱼,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望援制。 院中可真熱鬧戏挡,春花似錦、人聲如沸晨仑。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)洪己。三九已至妥凳,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間答捕,已是汗流浹背逝钥。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留拱镐,地道東北人艘款。 一個(gè)月前我還...
    沈念sama閱讀 48,063評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像沃琅,于是被迫代替她去往敵國(guó)和親哗咆。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評(píng)論 2 354

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理益眉,服務(wù)發(fā)現(xiàn)晌柬,斷路器,智...
    卡卡羅2017閱讀 134,656評(píng)論 18 139
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,810評(píng)論 6 342
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,118評(píng)論 25 707
  • 姓名:羅江漢 公司:東莞市旭瑞光電科技有限公司 組別:第230期努力二組 【日精進(jìn)打卡第 66天】 【知~學(xué)習(xí)】 ...
    羅江漢閱讀 200評(píng)論 0 0
  • *紅色入心:西紅柿呜叫、紅蘿卜空繁、枸杞、紅棗朱庆、紅肉椒盛泡。 *綠色入肝:芹菜、波菜娱颊,空心菜傲诵,西蘭花等 綠色蔬菜。 *黃色入脾...
    快樂(lè)中姐閱讀 221評(píng)論 0 0