2011-08-25 18 views
4

在我現在的基於Spring的web應用程序項目上,開發人員已經爲每個函數寫入了兩條日誌語句。一個日誌入口函數,另一個日誌退出。這個想法是追蹤執行路徑 - 至少是一個功能級別。如何跟蹤進入和退出基於Spring的Web應用程序的所有功能?

有沒有辦法做到這一點,而沒有亂拋垃圾的整個代碼庫與這些重複的陳述?

要清楚,我們想要記錄所有函數,而不僅僅是Spring bean的公共方法。

+2

工作這可能有一些幫助 - http:// stackoverflow。com/questions/2071050/is-using-spring-aop-for-logging-a-good-idea – adarshr

+0

通常,選擇代表決策點的重要方法以及記錄方法+參數的入口和方法+退出時返回值。缺點是這需要少量的實際思考。 – Kevin

+0

實際思考,ey?這不會,Kevin;) –

回答

3

你可以用Spring AOP來做到這一點。

Spring AOP將允許您在方法調用之前和/或之後「攔截」方法調用並執行任意代碼。您還可以檢查參數並返回這些方法的值。

達到你所談論的記錄,你會做這樣的事情,有可能使用around advice

  1. 攔截所有方法調用(或最好,只有那些你有興趣)。
  2. 做'之前的方法'日誌記錄。
  3. 調用該方法。
  4. 做你'後法'記錄。

所有有關如何做到這一點的Spring細節可以在提供的文檔中找到。

+1

這是否意味着我想記錄的任何對象都必須是Spring bean? –

+0

類別。我認爲如果你也使用Spring支持的'AspectJ',你可以做任何bean。在Spring AOP文檔中,查看第7.8節及其子節。 –

+0

@ MikeM.Lin您可以分享一個示例或參考教程嗎? –

0

與尼古拉斯相同的想法。你可以使用Spring AOP來做到這一點。

我喜歡使用註釋,以便在源代碼中指定邏輯,而不是在方面的建議中指定。

定義的註釋

package aop; 
@Target({ElementType.METHOD}) 
@Retention(RetentionPolicy.RUNTIME) 
public @interface Traceable {} 

定義方面

package aop; 
@Aspect 
public class TraceableAspect { 

    private final static AtomicLong Count = new AtomicLong(0); 

    @Around("execution(* *(..)) && @annotation(aop.Traceable)") 
    public Object aroundTraceableMethod(ProceedingJoinPoint pjp) throws Throwable { 

     Logger logger = LoggerFactory.getLogger(pjp.getTarget().getClass()); 
     if (logger.isTraceEnabled()) { 
      return executeWithTrace(pjp, logger, Count.incrementAndGet()); 
     } 

     return pjp.proceed(); 
    } 

    private Object executeWithTrace(ProceedingJoinPoint pjp, Logger logger, long id) throws Throwable { 

     long start = System.currentTimeMillis(); 
     try { 
      logger.trace(String.format("#### - #%d - Starting execution of method '%s'", id, pjp.toShortString())); 
      return pjp.proceed(); 
     } catch (Throwable throwable) { 
      logger.error(String.format("#### - #%d - Error while executing method '%s' : %s", id, pjp.toShortString(), throwable.toString())); 
      throw throwable; 
     } finally { 
      if (logger.isTraceEnabled()) { 
       logger.trace(String.format("#### - #%d - End of method '%s' (duration %s ms)", id, pjp.toShortString(), (System.currentTimeMillis() - start))); 
      } 
     } 
    }  
} 

使用在春季啓動項目方面

package project; 
@Profile("with-trace-aop") 
@Configuration 
@EnableAspectJAutoProxy(proxyTargetClass = true) 
public class SecToolWebApplicationTraceableAspect extends aop.TraceableAspect { 

    @PostConstruct 
    public void init(){ 
     Logger logger = LoggerFactory.getLogger(this.getClass()); 
     logger.warn("###-AOP-### TraceableAspect initialized for this application"); 
    } 
} 

**在控制器

package project; 
@RestController 
public class ModelController { 

    @Traceable 
    @RequestMapping(method = RequestMethod.GET, value = "/{date}") 
    @ResponseBody 
    public <Collection<TE> find(@PathVariable @DateTimeFormat(pattern = DateUtils.DATE_FORMAT) Date date) { 
    ... 
    } 
} 

重要當一個類被鏈接到通知的一個跟蹤方法中,所有的「最終」的方法沒有更多的調用。不使用「最終」

因此,假設跟蹤模式記錄被激活是很重要的,該方法的每次調用「發現」將被追蹤

注意這不,如果

相關問題