午夜精品福利视频,亚洲激情专区,免费看a网站,aa毛片,亚洲色图激情小说,亚洲一级毛片,免费一级毛片一级毛片aa

基于AOP的日志調(diào)試 -管理資料

管理資料 時間:2019-01-01 我要投稿
【www.stanzs.com - 管理資料】

   

斷點 vs 日志

    斷點是我們?nèi)粘i_發(fā)最為常見和高效的調(diào)試手段, 相比較輸入日志它給予更多的狀態(tài)信息和靈活的觀察角度, 但斷點調(diào)試是有前提和局限的.

    需要一個界面友好, 功能強大的IDE,

    比較適合于在單機的開發(fā)環(huán)境中進行.

    企業(yè)應(yīng)用開發(fā)中, 我們常常會遇到無法斷點調(diào)試的窘境, 例如:

    這個異常僅在生產(chǎn)環(huán)境出現(xiàn), 開發(fā)環(huán)境里無法重現(xiàn);

    存在外部系統(tǒng)依賴, 開發(fā)環(huán)境無法模擬等.

    這迫使我們不得不回到日志調(diào)試的老路子上來.

Print vs Logging

    簡單點的話, 我們用

System.out.println("debug infomation");

    就是因為過于簡單, 當(dāng)需要更多信息(如線程, 時間等), 或是定義輸出模式和形式就需要編寫更多代碼, 于是我們有了Log4j.

為什么要基于AOP

    Log4j挺好用的, 只是與System.out.print一樣, 在代碼中隨處可見, 但卻沒有業(yè)務(wù)價值.

    更令人頭痛的是, 并非每次我們都有足夠的經(jīng)驗告訴自己應(yīng)該在哪里添加這些語句, 以致于調(diào)試中不斷的因為調(diào)正它們的在代碼中的位置, 而反復(fù)編譯 – 打包 – 發(fā)布系統(tǒng). 這種體力活, 太沒藝術(shù)感了, 囧!

    換而言之, 我們會希望:

    將Logging剝離于業(yè)務(wù)之外, 讓代碼更易于維護,

    無需重新編譯,甚至能夠運行時, 可調(diào)整輸出日志的位置.

    AOP完全可以幫助我們做到上述兩點.

    這完全不是什么新鮮觀點, 這在任何介紹AOP文章中, 都會提到Logging是其最典型的應(yīng)用場景.

    所以這兒將基于Guice, 討論如何實現(xiàn)一個非侵入式的, 且能無需重新編譯即可調(diào)正Logging位置的簡單示例.

一個基于Guice的示例

    我曾經(jīng)用過一個叫Log4E的Eclipse插件, 它可根據(jù)我們預(yù)先的配置, 自動的為我們在編寫的代碼中插入logging的語句, 如方法調(diào)用的進口和出口:

public int sum(int a, int b){  if (logger.isDebugEnabled()){    logger.debug("sum - start : a is " + a + ", b is " + b);  }  int result = a + b;  if (logger.isDebugEnabled()){    logger.debug("sum - end : return is " + result);  }}

    從上例不難發(fā)現(xiàn), 我們在調(diào)試過程中, 往往會通過一個方法的進入或退出的狀態(tài)(參數(shù), 返回值或異常)來分析問題出在什么地方. 那么, 借助MethodInterceptor我們可以這樣做:

Logging

public class LoggingInterceptor implements MethodInterceptor {  @Override  public Object invoke(MethodInvocation invocation) throws Throwable {    try {      Object result = invocation.proceed();      // logging 方法, 參數(shù)與返回值      log(invocation.getMethod(), invocation.getArguments(), result);      return result;    } catch (Throwable throwable) {      // logging 方法, 參數(shù)與異常      error(invocation.getMethod(), invocation.getArguments(), throwable);      throw throwable;    }  }}

    接下來, 我們需要配置這個 , 并向Guice聲明它.

public class LoggingModule extends AbstractModule {  @Override  public void configure() {    bindInterceptor(Matchers.any(), Matchers.any(), new LoggingInterceptor());  }}public class Main {  public static void main(String[] args) {    Injector injector = Guice.createInjector(new BusinessModule(), new LoggingModule());  }}

    很簡單, 不是嗎? 這樣我們的業(yè)務(wù)模塊的代碼完全不用編寫輸出日志的代碼, 只需要在創(chuàng)建Injector的時候加入LoggingModule就可以了.

    等等, 好像忘了去實現(xiàn)如何配置日志輸出的位置. 好吧, 這個其實很簡單:

配置Logging位置

bindInterceptor(Matchers.any(), Matchers.any(), new LoggingInterceptor());

    bindInterceptor方法的第一個參數(shù)定義了 將匹配所有類, 第二個參數(shù)定義了 將匹配一個類所有方法. 那么, 我們要做的僅僅是通過外部參數(shù)調(diào)整這兩個參數(shù)就可以啦. 這兒就演示一個用正則表達式匹配要Logging的方法的例子:

public class MethodRegexMatcher extends AbstractMatcher<Method> {  private final Pattern pattern = Pattern.compile(System.getProperty("logging.method.regex", "*"));  @Override  public boolean matches(Method method) {    return pattern.matcher(method.getName()).matches();  }}

    可惜這種方法不能在運行時調(diào)整, 但這也是可以實現(xiàn)的.

運行時配置Logging位置

    還是以用正則表達式匹配要Logging的方法為例:

public class LoggingInterceptor implements MethodInterceptor {  private String regex = "*";      public void setMethodRegex(String regex){    this.regex = regex;  }  @Override  public Object invoke(MethodInvocation invocation) throws Throwable {    String methodName = invocation.getMethod().getName();        try {      Object result = invocation.proceed();                  if (methodName.matches(regex))        // logging 方法, 參數(shù)與返回值        log(invocation.getMethod(), invocation.getArguments(), result);      return result;    } catch (Throwable throwable) {      if (methodName.matches(regex))        // logging 方法, 參數(shù)與異常        error(invocation.getMethod(), invocation.getArguments(), throwable);      throw throwable;    }  }}

    而后可借助JMX動態(tài)調(diào)整regex的值, 來實現(xiàn)運行時的配置. 當(dāng)然, 肯定還會有其它更好的方法, 如果你知道了不妨分享一下.

小結(jié)

    本文僅以Guice為例討論如何改進我們?nèi)粘i_發(fā)中調(diào)試的問題, 其實這在Spring應(yīng)用也同樣能夠?qū)崿F(xiàn)的, 甚至其它應(yīng)用AOP的場景都是可行的.

    拓展開來, 不僅是Logging, 說不定驗證(測試)也是可行的呢!

    有句話不是這樣說的嗎, “思想有多遠, 我們就能走多遠!”

最新文章
推薦文章