【Java框架型專案從入門到裝逼】第二節 - Spring框架 AOP

westwolf發表於2021-09-09

繼續上一節的內容,多幾個jar包:
圖片描述

aop技術是面向切面程式設計思想,作為OOP的延續思想新增到企業開發中,用於彌補OOP開發過程中的缺陷而提出的程式設計思想。AOP底層也是物件導向;只不過面向的不是普通的Object物件,而是特殊的AOP物件。AOP的關注點是組成系統的非核心通用服務模組(比如登入檢查等),相對於普通物件,aop不需要透過繼承、方法呼叫的方式來提供功能,只需要在xml檔案中以引用的方式,將非核心服務功能引用給需要改功能的核心業務邏輯物件或方法中。最終實現物件的解耦。spring 中ioc技術實現了核心業務邏輯物件之間的解耦(如LoginAction與DaoImpl)
圖片描述

AOP可以說是Spring中最難理解的一個知識點了,你可能網上找了很多資料,也買過很多本書,但都不是很理解到底什麼是AOP?我曾經也是琢磨了好久才有了一定的瞭解。那麼,到底怎麼講這個知識點呢。來不及解釋了,快上車!聽完這個例子,我相信你一定會對AOP有一個非常深刻的理解!
讓我們新建一個英雄類:

package com.spring.bean;

public class Hero {

    private String heroName;
    private String type;
    private String description;

    public String getHeroName() {
        return heroName;
    }
    public void setHeroName(String heroName) {
        this.heroName = heroName;
    }
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
    public String getDescription() {
        return description;
    }
    public void setDescription(String description) {
        this.description = description;
    }
    @Override
    public String toString() {
        return "Hero [heroName=" + heroName + ", type=" + type + ", description=" + description + "]";
    }

}

再來個露娜類,繼承自英雄類:

圖片描述

啊啊啊,放錯圖片了,應該是這個:

圖片描述

package com.spring.bean;

public class Luna extends Hero{

    /**
     * 秀操作
     */
    public void operation(){
        System.out.println("看我月下無限連!");
    }

    /**
     * 跑路
     */
    public void run(){
        System.out.println("我操,大空了,趕緊跑!");
    }

    /**
     * 發資訊
     * @param str
     */
    public void say(String str){
        System.out.println(str);
    }

}

可以看到,露娜類有三個方法,分別是秀操作,跑路和發資訊。
再寫一個團戰類:

package com.spring.test;

import com.spring.bean.Luna;

/**
 * 團戰類
 * @author Administrator
 *
 */
public class Battle {

    public void tuan(){
        Luna luna = new Luna();
        luna.say("上去開團!");
        luna.operation();

    }

}

測試程式碼如下:

ApplicationContext context = new ClassPathXmlApplicationContext("spring-aop.xml");
Battle battle = (Battle)context.getBean("Battle");
battle.tuan();

我們用spring把Battle類配上去。

spring-aop.xml

執行測試程式碼:
圖片描述
圖片描述

在團戰方法裡面,我們新建一個露娜的物件,然後發出資訊“上去開團”,接著又秀了一把操作。這是一個比較普通的流程。而事實上,露娜可能需要在團戰前就提醒我方隊友“等我集合打團”,不要人都沒齊,隊友就無腦往前衝。OK,我們如何透過程式碼來實現這個過程呢?很顯然,這個過程需要在團戰方法執行之前就被執行。這就需要AOP面向切面的技術了。

我們需要寫一個類,實現MethodBeforeAdvice介面。

/**
 * Notice 定義一個通知打團的訊號 - 團戰之前
 * @author Administrator
 *
 */
public class BeforeTuanZhan implements MethodBeforeAdvice{

    @Override
    public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
        System.out.print(this.getClass().getName() + " -- ");
        Luna luna = new Luna();
        luna.setHeroName("露娜");
        luna.setType("戰士/法師");
        luna.setDescription("月光女神");
        luna.say("等我集合打團!");

    }

}

我們希望這個方法在團戰之前就被執行,怎麼做呢?沒錯,就是在XML檔案中做如下配置:

<!-- 定義所有可供露娜切入的點(方法) --&gt<!-- 原則上只要時機正確,任何團戰露娜都可以切進去! --&gt

execution( com.spring.test.Battle.(..))
這句話的含義就是,返回值為任意,com.spring.test包裡面的Battle類,這個類裡面所有的方法都需要切入。所謂的切入,就是在方法執行前,執行中,發生異常的時候執行某個其他的方法。執行中用的不多,一般就用另外三種情況。

現在,我們重新執行測試程式碼:

ApplicationContext context = new ClassPathXmlApplicationContext("spring-aop.xml");
Battle battle = (Battle)context.getBean("Battle");
battle.tuan();

圖片描述

現在各位想一下,如果團戰打贏了怎麼辦,是不是馬上就該去推塔或者打龍啊,這個時候,如果隊友團戰打贏了就發呆,那就很坑了。所以呢,你這個時候就得提醒隊友下一步該做什麼,這個提醒的步驟是在團戰方法執行結束後才發生的。

我們需要新建一個AfterTuanZhan類,實現AfterReturningAdvice介面。

/**
 * Notice 定義一個團戰結束後的類 - 團戰之後
 * @author Administrator
 */
public class AfterTuanZhan implements AfterReturningAdvice{

    @Override
    public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {
        System.out.print(this.getClass().getName() + " -- ");
        Luna luna = new Luna();
        luna.setHeroName("露娜");
        luna.setType("戰士/法師");
        luna.setDescription("月光女神");
        luna.say("進攻敵方防禦塔!");
    }

}

配置到spring-aop.xml中:

<!-- 定義一個切面 --&gt<!-- 定義所有可供露娜切入的點(方法) --&gt<!-- 原則上只要時機正確,任何團戰露娜都可以切進去! --&gt

現在,我們重新執行測試程式碼:

ApplicationContext context = new ClassPathXmlApplicationContext("spring-aop.xml");
Battle battle = (Battle)context.getBean("Battle");
battle.tuan();

圖片描述

再來說說萬一團戰失利的情況,比如露娜斷大了咋辦,沒錯,這個時候就是團戰發生了異常,我們在Battle類中手動設定一個異常:

/**
 * 團戰類
 * @author Administrator
 *
 */
public class Battle {

    public void tuan(){
        Luna luna = new Luna();
        luna.say("上去開團!");
        luna.operation();

        int i = 1 / 0 ;

    }

}

然後,編寫TuanZhanException類,實現ThrowsAdvice介面:

/**
 * 定義一個團戰異常類,萬一出現情況就進入這個類
 * @author Administrator
 *
 */
public class TuanZhanException implements ThrowsAdvice {

    //該方法會在露娜團戰出現異常後自動執行
    public void afterThrowing(Method method, Object[] args, 
            Object target, Exception ex){
        System.out.print(this.getClass().getName() + " -- ");
        Luna luna = new Luna();
        luna.run();
    }
}

配置到spring-aop,xml:

<!-- 定義一個切面 --&gt<!-- 定義所有可供露娜切入的點(方法) --&gt<!-- 原則上只要時機正確,任何團戰露娜都可以切進去! --&gt

現在,我們重新執行測試程式碼:

ApplicationContext context = new ClassPathXmlApplicationContext("spring-aop.xml");
Battle battle = (Battle)context.getBean("Battle");
battle.tuan();

圖片描述

總結:

1. aop面向切面,切的是什麼,沒錯,切的是方法!
2. 怎麼切,你記好了,就是你先自己規定哪些方法需要切,然後設定切入的方式:方法執行之前做什麼,執行之後做什麼,如果方法出現異常,又要做什麼?另外還有一種方法執行的過程中做什麼,只是用的比較少,反正我還沒有見過在哪裡用了。用的最多的就是發生異常後做什麼,比如事務管理。

圖片描述

密碼:om9i

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4662/viewspace-2808204/,如需轉載,請註明出處,否則將追究法律責任。

相關文章