Spring2.0 AOP 之Before,After,Thrown,Around Advice(一)

在Spring 2.0裏要使用AOP的話,大大的簡化了,不管是程序書寫還是xml 配置,下面我說一下我的學習和使用過程:

 

我以日誌功能爲例子,假如我們寫了一個method,然後我們想在這個method執行做一件事,執行後做一件事,或是發生異常時怎麼樣,有的人在想那還不簡單,我直接在在這個方法里加上不就行了,但是再想想當一個項目做大後,用這種方法會給以後的維護帶來很多麻煩,因爲你已經把這些本不屬於程序邏輯的事情也耦合到裏面了,如果加的地方多的話,以後麻煩可就大了,而利用Spring AOP  想加這個日誌功能就簡單了,完全與程序邏輯解耦,以後想添改什麼的,單獨去處理就方便好多了。在Spring 2.0裏不再需要去實現好多的接口去做這些事情,配置也很簡單了,

 

講解背景如下:

我有一個接口 IHello

 

public interface IHello {
    public void hello(String name);
}

 

有一個實現類HelloSpeaker

 

public class HelloSpeaker implements IHello {

    public void hello(String name) {
        System.out.println("Hello,"+name);
    }

}

 

 1.Before Advice

  現在我想在hello方法執行前加個log怎麼做呢,這裏我們要加個class 叫 LogAspect

 

 專門去處理log

 

 public class LogAspect {
   
    private Logger logger=Logger.getLogger(this.getClass().getName());

 

    public void before(JoinPoint jointPoint) {
        logger.log(Level.INFO, "method starts..."
                + jointPoint.getSignature().getDeclaringTypeName() + "."
                + jointPoint.getSignature().getName());
    }

}

 

 然後建個spring基於xml schema的文件

 

 

 

再寫個TestClass

 

    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans-config.xml");
        IHello helloSpeaker=(IHello)context.getBean("helloSpeaker");
        helloSpeaker.hello("Jack");
    }

 

 現在可運行了,但是運行前確保加上asm-*.jar 2.2.1或2.2.2 version ,asm-attrs-2.2.2.jar, asm-commons.jar我的是2.2.的

 

 aspectjweaver-1.5.3.jar     commons-logging-1.0.4.jar

 

spring所需的就不用說了。然後運行結果如下:

 

2009-2-23 15:38:59 LogAspect before
信息: method starts...IHello.hello

Hello,Jack

 

2.After Advice

 

有兩種:After和Afterreturning(可以設置目標方法調用的傳回值)

 

現在原LogAspec里加個方法:

 

    public void after(JoinPoint jointPoint){
        logger.log(Level.INFO, "method ends..."
                + jointPoint.getSignature().getDeclaringTypeName() + "."
                + jointPoint.getSignature().getName());
    }

beans-config.xml里加上:

 

<aop:after pointcut-ref="logHello" method="after"/>

 

運行後成了:

 

2009-2-23 15:42:27 LogAspect before
信息: method starts...IHello.hello
2009-2-23 15:42:27 LogAspect after
信息: method ends...IHello.hello
Hello,Jack

 

有人說不對啊,這哪裏是前和後啊,這裏要說明,log是由另一個線程進行操作的,並不影響原有程序的流程。

 

 

3.After Throwing Advice:

 

現在原LogAspec里加個方法:

 

    public void afterThrowing(JoinPoint jointPoint,Throwable throwable){
        logger.log(Level.INFO, "Logging that a " + throwable +
                "/nException was thrown in..."+
                jointPoint.getSignature().getDeclaringTypeName() + "."
                + jointPoint.getSignature().getName());
    }

 

配置文件:

 

 <aop:after-throwing pointcut-ref="logHello" throwing="throwable" method="afterThrowing"/>

 

現在故意把hello裏修改一下讓其引發異常:

 

System.out.println("Hello,"+Integer.parseInt(name));//Testing Exception

 

運行結果如下:

 

2009-2-23 15:46:30 LogAspect before
信息: method starts...IHello.hello
2009-2-23 15:46:30 LogAspect after
信息: method ends...IHello.hello
2009-2-23 15:46:30 LogAspect afterThrowing
信息: Logging that a java.lang.NumberFormatException: For input string: "Jack"
Exception was thrown in...IHello.hello
java.lang.NumberFormatException: For input string: "Jack"

 

 

4. Around Advice :

 

這個可以實現在前和後加上log

 

同樣增加一個方法:

 

    public Object invoke(ProceedingJoinPoint jointPoint) throws Throwable{
       
        logger.log(Level.INFO, "method starts..."
                + jointPoint.getSignature().getDeclaringTypeName() + "."
                + jointPoint.getSignature().getName());
       
        Object retVal=jointPoint.proceed();
       
        logger.log(Level.INFO, "method ends..."
                + jointPoint.getSignature().getDeclaringTypeName() + "."
                + jointPoint.getSignature().getName());

       
        return retVal;
    }

 

 

配置xml文件:

 

<aop:around pointcut-ref="logHello" method="invoke"/>

 

運行結果如下:

 

2009-2-23 15:49:04 LogAspect invoke
信息: method starts...IHello.hello
2009-2-23 15:49:04 LogAspect afterThrowing
信息: Logging that a java.lang.NumberFormatException: For input string: "Jack"
Exception was thrown in...IHello.hello
java.lang.NumberFormatException: For input string: "Jack"

 

大家一看就會發現啊!後面的log沒有執行,這裏可以告訴我們用Around實現前和後加入log和分別用Before和After的區別之一了。

 

 

 未完待續

 

[轉載請註明出處]

發佈了32 篇原創文章 · 獲贊 4 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章