Spring-1.依賴注入(BI)和面向切面編程(AOP)

1 依賴注入

通過依賴注入(Dependency Injection, DI)扰她,對(duì)象的依賴關(guān)系將由系統(tǒng)中負(fù)責(zé)協(xié)調(diào)各對(duì)象的第三方組件在創(chuàng)建對(duì)象的時(shí)候進(jìn)行設(shè)定纺涤。

1.1 實(shí)現(xiàn)

對(duì)于如下類

package com.junzerg.spring_knight;

public class BraveKnight implements Knight {

    private Quest quest;

    public BraveKnight(Quest quest) {
        this.quest = quest;
    }

    public void embarkOnQuest() {
        quest.embark();
    }
}
  1. BraveKnight沒有自己創(chuàng)建探險(xiǎn)任務(wù)湖笨,而是在構(gòu)造的時(shí)候把探險(xiǎn)任務(wù)作為構(gòu)造器參數(shù)傳入颁湖。這是依賴注入的一種方式嘀趟,構(gòu)造器注入(constructor injection)雄驹。
  2. 傳入的探險(xiǎn)類型Quest,是所有的探險(xiǎn)任務(wù)都必須實(shí)現(xiàn)的一個(gè)接口荣堰。
  3. BraveKnight沒有與特定的Quest實(shí)現(xiàn)發(fā)生耦合床未,只要求探險(xiǎn)任務(wù)實(shí)現(xiàn)了Quest接口。

可以看出:
DI帶來的最大的好處就是松耦合振坚。如果一個(gè)對(duì)象只通過接口(而不是具體實(shí)現(xiàn)或者初始化過程)來表明依賴關(guān)系薇搁,那么這種依賴就能在對(duì)象本身毫不知情的情況下,用不同的具體實(shí)現(xiàn)進(jìn)行替換渡八。

1.2 注入

對(duì)于#1中的BraveKnight類啃洋。可以接受任意一種Quest的實(shí)現(xiàn)屎鳍,例如如下類:

package com.junzerg.spring_knight;

import java.io.PrintStream;

public class SlayDragonQuest implements Quest {

    private PrintStream stream;

    public SlayDragonQuest(PrintStream stream) {
        this.stream = stream;
    }

    public void embark() {
        stream.println("Embarking on quest to slay the dragon!");
    }
}

創(chuàng)建了這個(gè)類之后宏娄,剩下的就是將這個(gè)類交給BraveKnight。這就是創(chuàng)建應(yīng)用組件之間的寫作的行為逮壁,被稱為裝配(wiring)孵坚。

1.3 裝配

Spring支持兩種裝配的方式。

1.3.1 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">

    <bean id="knight" class="com.junzerg.spring_knight.BraveKnight">
        <constructor-arg ref="quest" />
    </bean>

    <bean id="quest" class="com.junzerg.spring_knight.SlayDragonQuest">
        <constructor-arg value="#{T(System).out}" />
    </bean>

</beans>

以上配置功能為:

  1. 將BraveKnight和SlayDragonQuest聲明為Spring中的bean窥淆。
  2. 在構(gòu)造BraveKnight bean的時(shí)候傳入SlayDragonQuest bean的應(yīng)用十饥,作為構(gòu)造器的參數(shù)。
  3. 在構(gòu)造SlayDragonQuest bean的時(shí)候?qū)ystem.out傳入到構(gòu)造器中祖乳。
1.3.2 Java描述配置
package com.junzerg.spring_knight.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.junzerg.spring_knight.BraveKnight;
import com.junzerg.spring_knight.Knight;
import com.junzerg.spring_knight.Quest;
import com.junzerg.spring_knight.SlayDragonQuest;

@Configuration
public class KnightConfig {
    
    @Bean
    public Knight knight() {
        return new BraveKnight(quest());
    }
    
    @Bean
    public Quest quest() {
        return new SlayDragonQuest(System.out);
    }
}

作用和用 xml配置的一樣逗堵。

1.4 實(shí)現(xiàn)

1.4.1 xml配置的實(shí)現(xiàn)

對(duì)于xml配置的情況,使用ClassPathXmlApplicationContext(加載位于應(yīng)用程序類路徑下的一個(gè)或者多個(gè)XML配置文件)眷昆。

package com.junzerg.spring_knight;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class KnightMain {

    @Autowired
    Knight knight;

    public static void main(String[] args) throws Exception {
         ClassPathXmlApplicationContext context = new
         ClassPathXmlApplicationContext("META-INF/spring/knight.xml");
         Knight knight = context.getBean(Knight.class);
         knight.embarkOnQuest();
         context.close();
    }
}
1.4.2 Java配置的實(shí)現(xiàn)

對(duì)于Java配置的情況蜒秤,使用AnnotationConfigApplicationContext。

package com.junzerg.spring_knight;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.junzerg.spring_knight.config.KnightConfig;

public class KnightMain {

    @Autowired
    Knight knight;

    public static void main(String[] args) throws Exception {

        AnnotationConfigApplicationContext content = new AnnotationConfigApplicationContext(KnightConfig.class);
        Knight knight = content.getBean(Knight.class);
        knight.embarkOnQuest();
    }
}

1.5 上下文中其他類和結(jié)果

1.5.1 上下文中其他類
  1. Knight
package com.junzerg.spring_knight;

public interface Knight {

    void embarkOnQuest();

}
  1. Quest
package com.junzerg.spring_knight;

public interface Quest {

    void embark();

}
1.5.2 運(yùn)行結(jié)果:

Embarking on quest to slay the dragon!

1.5.3 Maven

我是在Maven中添加Spring依賴的亚斋,這一節(jié)只需要用到Spring的上下文(context)依賴作媚,如下:

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

2 面向切面編程(AOP)

通過面向切面編程(aspect-oriented programming, AOP),把遍布應(yīng)用各處的功能分離出來形成可重用的組件帅刊。
AOP將橫切關(guān)注點(diǎn)(跨越系統(tǒng)的多個(gè)組件纸泡,例如日子,事務(wù)管理赖瞒,安全等)模塊化女揭,并以聲明的方式將它們應(yīng)用到需要影響的組件中去蚤假,這樣能夠使這些組件有更高的內(nèi)聚性并且會(huì)更加關(guān)注自身的業(yè)務(wù),不需要了解涉及系統(tǒng)服務(wù)帶來的復(fù)雜性吧兔,從而保證了POJO的簡單性磷仰。

2.1 AOP簡單應(yīng)用

對(duì)于#1中的騎士的事跡,用一個(gè)吟游詩人來記載境蔼。

package com.junzerg.spring_knight;

import java.io.PrintStream;

public class Minstrel {

    private PrintStream stream;

    public Minstrel(PrintStream stream) {
        this.stream = stream;
    }

    public void singBeforeQuest() {
        stream.println("Fa la la, the knight is so brave!");
    }

    public void singAfterQuest() {
        stream.println("Tee hee hee, the brave knight " + "did embark on a quest!");
    }

}

Minstrel類灶平,在騎士執(zhí)行每一個(gè)探險(xiǎn)任務(wù)之前,singBeforeQuest被調(diào)用箍土;在騎士完成探險(xiǎn)任務(wù)之后逢享,singAfterQuest()方法會(huì)被調(diào)用;這兩種情況都通過PrintStream類來歌頌事跡吴藻,這個(gè)類是通過構(gòu)造器來引入的拼苍。

**那么,在普通情況下调缨,編寫這個(gè)類之后,會(huì)在BraceKnight中使用這個(gè)類吆你。但是利用AOP弦叶,可以在騎士類不訪問吟游詩人類的情況下,讓吟游詩人歌頌騎士的事跡妇多。

這種技術(shù)是通過在Spring配置文件中將Minstrel聲明為一個(gè)切面實(shí)現(xiàn)的伤哺。

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

    <bean id="knight" class="sia.knights.BraveKnight">
        <constructor-arg ref="quest" />
    </bean>

    <bean id="quest" class="sia.knights.SlayDragonQuest">
        <constructor-arg value="#{T(System).out}" />
    </bean>

    <bean id="minstrel" class="sia.knights.Minstrel">
        <constructor-arg value="#{T(System).out}" />
    </bean>

    <aop:config>
        <aop:aspect ref="minstrel">
            <aop:pointcut id="embark" expression="execution(* *.embarkOnQuest(..))" />

            <aop:before pointcut-ref="embark" method="singBeforeQuest" />

            <aop:after pointcut-ref="embark" method="singAfterQuest" />
        </aop:aspect>
    </aop:config>

</beans>

2.3 結(jié)果和Maven

2.3.1 結(jié)果

Fa la la, the knight is so brave!
Embarking on quest to slay the dragon!
Tee hee hee, the brave knight did embark on a quest!

2.3.2 Maven

本節(jié)中利用到了AspectJ切點(diǎn)表達(dá)式,需要在Maven中添加如下依賴:

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjrt</artifactId>
    <version>1.8.10</version>
</dependency>

<dependency>
    <groupId>aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.5.4</version>
</dependency>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末者祖,一起剝皮案震驚了整個(gè)濱河市立莉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌七问,老刑警劉巖蜓耻,帶你破解...
    沈念sama閱讀 206,839評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異械巡,居然都是意外死亡刹淌,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門讥耗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來有勾,“玉大人,你說我怎么就攤上這事古程“ǎ” “怎么了?”我有些...
    開封第一講書人閱讀 153,116評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵挣磨,是天一觀的道長雇逞。 經(jīng)常有香客問我荤懂,道長,這世上最難降的妖魔是什么喝峦? 我笑而不...
    開封第一講書人閱讀 55,371評(píng)論 1 279
  • 正文 為了忘掉前任势誊,我火速辦了婚禮,結(jié)果婚禮上谣蠢,老公的妹妹穿的比我還像新娘粟耻。我一直安慰自己,他們只是感情好眉踱,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評(píng)論 5 374
  • 文/花漫 我一把揭開白布挤忙。 她就那樣靜靜地躺著,像睡著了一般谈喳。 火紅的嫁衣襯著肌膚如雪册烈。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,111評(píng)論 1 285
  • 那天婿禽,我揣著相機(jī)與錄音赏僧,去河邊找鬼。 笑死扭倾,一個(gè)胖子當(dāng)著我的面吹牛淀零,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播膛壹,決...
    沈念sama閱讀 38,416評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼驾中,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了模聋?” 一聲冷哼從身側(cè)響起肩民,我...
    開封第一講書人閱讀 37,053評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎链方,沒想到半個(gè)月后持痰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,558評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡祟蚀,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評(píng)論 2 325
  • 正文 我和宋清朗相戀三年共啃,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片暂题。...
    茶點(diǎn)故事閱讀 38,117評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡移剪,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出薪者,到底是詐尸還是另有隱情纵苛,我是刑警寧澤,帶...
    沈念sama閱讀 33,756評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站攻人,受9級(jí)特大地震影響取试,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜怀吻,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評(píng)論 3 307
  • 文/蒙蒙 一瞬浓、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蓬坡,春花似錦猿棉、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至兆龙,卻和暖如春杖爽,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背紫皇。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評(píng)論 1 262
  • 我被黑心中介騙來泰國打工慰安, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人聪铺。 一個(gè)月前我還...
    沈念sama閱讀 45,578評(píng)論 2 355
  • 正文 我出身青樓化焕,卻偏偏與公主長得像,于是被迫代替她去往敵國和親计寇。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評(píng)論 2 345

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

  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理脂倦,服務(wù)發(fā)現(xiàn)番宁,斷路器,智...
    卡卡羅2017閱讀 134,600評(píng)論 18 139
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,748評(píng)論 6 342
  • 縱覽Spring 赖阻, 讀者會(huì)發(fā)現(xiàn)Spring 可以做非常多的事情蝶押。 但歸根結(jié)底, 支撐Spring的僅僅是少許的基...
    六尺帳篷閱讀 1,621評(píng)論 0 12
  • 最開始認(rèn)識(shí)你的時(shí)候火欧,其實(shí)我的心里是抱有一些成見的棋电,第一次知道你是在《快樂大本營》的舞臺(tái)上,那時(shí)的你面對(duì)鏡頭還是有那...
    噢吧碼閱讀 737評(píng)論 7 7
  • 新鮮新鮮新鮮。榆浓。于未。像被念過咒語一樣,這個(gè)概念已經(jīng)植入到了寒冰童鞋腦子里。寒冰童鞋本來是撕烤人參的販子烘浦,現(xiàn)在悲摧變身...
    冰小寒閱讀 440評(píng)論 0 1