Spring AOP處理日志
Spring AOP處理日志AOP正在成為軟件開發(fā)的下一個圣杯。使用AOP,你可以將處理aspect的代碼注入主程序,
通常主程序的主要目的并不在于處理這些aspect。AOP可以防止代碼混亂。 為了理解AOP
如何做到這點,考慮一下記日志的工作。日志本身不太可能是你開發(fā)的主程序的主要任務(wù)。
如果能將“不可見的”、通用的日志代碼注入主程序中,那該多好啊。AOP可以幫助你做到。
Spring framework是很有前途的AOP技術(shù)。作為一種非侵略性的,輕型的AOP framework,你
無需使用預(yù)編譯器或其他的元標簽,便可以在Java程序中使用它。這意味著開發(fā)團隊里只需
一人要對付AOP framework,其他人還是象往常一樣編程。 AOP是很多直覺難以理解的術(shù)語的根源。
幸運的是,你只要理解三個概念,就可以編寫AOP模塊。這三個概念是:advice,pointcut和advisor。
advice是你想向別的程序內(nèi)部不同的地方注入的代碼。pointcut定義了需要注入advice的位置,通常
是某個特定的類的一個public方法。advisor是pointcut和advice的裝配器,是將advice注入主程序
中預(yù)定義位置的代碼。
既然我們知道了需要使用advisor向主要代碼中注入“不可見的”advice,讓我們實現(xiàn)一個Spring AOP的例子。
在這個例子中,我們將實現(xiàn)一個before advice,這意味著advice的代碼在被調(diào)用的public方法開始前被執(zhí)行。
以下是這個before advice的實現(xiàn)代碼:
代碼:
package com.company.springaop.test;
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
public class TestBeforeAdvice implements MethodBeforeAdvice { //這里還有after,Exception,around等Advice
/**
*before 是在方法執(zhí)行之前執(zhí)行advice的內(nèi)容,around是在方法執(zhí)行之前和之后都得到了執(zhí)行
*Exception是拋出異常的時候,可以使用aop的方法來統(tǒng)一處理業(yè)務(wù)的異常。
×在編程的時候,可以由專門的人處理業(yè)務(wù)的異常,其它人還是一樣的編程,不用考慮業(yè)務(wù)類異常的處理。
*/
public void before(Method m, Object[] args, Object target)
throws Throwable { //這里能用反射?
System.out.println("Hello world! (by "
+ this.getClass().getName()
+ ")");
}
}
接
口MethodBeforeAdvice只有一個方法before需要實現(xiàn),它定義了advice的實現(xiàn)。before方法共用三個參數(shù),它們提供了相當
豐富的信息。參數(shù)Method m是advice開始后執(zhí)行的方法。方法名稱可以用作判斷是否執(zhí)行代碼的條件。Object[]
args是傳給被調(diào)用的public方法的參數(shù)數(shù)組。當需要記日志時,參數(shù)args和被執(zhí)行方法的名稱,都是非常有用的信息。你也可以改變傳給m的參數(shù),
但要小心使用這個功能;編寫最初主程序的程序員并不知道主程序可能會和傳入?yún)?shù)的發(fā)生沖突。Object target是執(zhí)行方法m對象的引用。
在下面的BeanImpl類中,每個public方法調(diào)用前,都會執(zhí)行advice:
代碼:
package com.company.springaop.test;
public class BeanImpl implements Bean {
public void theMethod() {
System.out.println(this.getClass().getName()
+ "." + new Exception().getStackTrace()[0].getMethodName()
+ "()"
+ " says HELLO!");
}
}
類BeanImpl實現(xiàn)了下面的接口Bean:
代碼:
package com.company.springaop.test;
public interface Bean {
public void theMethod();
}
雖然不是必須使用接口,但面向接口而不是面向?qū)崿F(xiàn)編程是良好的編程實踐,Spring也鼓勵這樣做。
pointcut和advice通過配置文件來實現(xiàn),因此,接下來你只需編寫主方法的Java代碼:
代碼:
package com.company.springaop.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
public class Main {
public static void main(String[] args) {
//Read the configuration file
ApplicationContext ctx
= new FileSystemXmlApplicationContext("springconfig.xml");
//Instantiate an object
Bean x = (Bean) ctx.getBean("bean");
//Execute the public method of the bean (the test)
x.theMethod();
}
}
我們從讀入和處理配置文件開始,接下來馬上要創(chuàng)建它。這個配置文件將作為粘合程序不同部分的“膠水”。讀入和處理配置文件后,我們會得到一個創(chuàng)建工廠ctx。任何一個Spring管理的對象都必須通過這個工廠來創(chuàng)建。對象通過工廠創(chuàng)建后便可正常使用。
僅僅用配置文件便可把程序的每一部分組裝起來。
代碼: