使用Spring3.0的AOP結合log4j實現接口方法執行時間記錄

項目使用RPC提供的內部服務,需要監控每個接口方法的調用情況以及響應時間,如果接口方法開始和結束時都計時並將兩個時間相減得到響應時間,勢必對代碼的入侵太大。使用AOP剛好能很優雅的解決這個問題!

 

1.log4j的配置log4j.xml。這裏使用xml風格的配置

	<appender name="info-out" class="org.apache.log4j.DailyRollingFileAppender">
		<param name="File" value="/data/logs/hiluo-service/info.log" />
		<param name="DatePattern" value="'.'yyyy-MM-dd'.log'" />
		<layout class="org.apache.log4j.PatternLayout">
			<param name="ConversionPattern" value="%d{yyyy.MM.dd HH:mm:ss} [%C{1}:%M] %m%n" />
		</layout>
		<filter class="org.apache.log4j.varia.LevelRangeFilter">
			<param name="LevelMax" value="info" />
			<param name="LevelMin" value="info" />
			<param name="AcceptOnMatch" value="true" />
		</filter>
	</appender> 

log4j的配置參見:http://stonexmx.blog.163.com/blog/static/1221585872009716112428738/

PatternLayout輸出格式參見:http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/PatternLayout.html

value="%d{yyyy.MM.dd HH:mm:ss} [%C{1}:%M] %m%n",%C{1}-類名,如果使用%C將輸出類的全路徑名,%M-方法名

輸出類似以下內容:


 

 

2.MethodTimeAdvice.java 用來記錄時間

 

package yourpackage.utils;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.StopWatch;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class MethodTimeAdvice implements MethodInterceptor {

	private static final Logger Log = LoggerFactory
			.getLogger(MethodTimeAdvice.class);

	@Override
	public Object invoke(MethodInvocation invocation) throws Throwable {
		// 用 commons-lang 提供的 StopWatch 計時
		StopWatch clock = new StopWatch();
		clock.start(); // 計時開始
		Object result = invocation.proceed();
		clock.stop(); // 計時結束

		// 方法參數類型,轉換成簡單類型
		Class[] params = invocation.getMethod().getParameterTypes();
		String[] simpleParams = new String[params.length];
		for (int i = 0; i < params.length; i++) {
			simpleParams[i] = params[i].getSimpleName();
		}
		Object[] args = invocation.getArguments();

		Log.info("Takes:" + clock.getTime() + " ms ["
				+ invocation.getThis().getClass().getName() + "."
				+ invocation.getMethod().getName() + "("
				+ StringUtils.join(simpleParams, ",") + ")("
				+ StringUtils.join(args, ",") + ")] ");
		return result;
	}

}

 

3.applicationContext.xml

 

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
	default-lazy-init="true">
        <aop:aspectj-autoproxy />
	<bean id="methodTimeAdvice" class="cn.hiluo.openfire.utils.MethodTimeAdvice" />
	<aop:config>
		<!-- 用 AspectJ 的語法定義 Pointcut,這裏攔截 service 包中的所有方法 -->
		<aop:advisor id="methodTimeLog" advice-ref="methodTimeAdvice"
			pointcut="execution(* yourpackage.service.impl..*.*(..))" />
	</aop:config>
        <bean id="yourservice" class="**.impl.yourServiceImpl">
		
	</bean>
        。。。。。yourbeans
</beans>

 

4.注意需要加入Spring相關包,比較容易遺漏的:org.springframework.aop-3.0.6.RELEASE.jar,org.springframework.aspects-3.0.6.RELEASE.jar,aspectjweaver-1.5.3.jar,aopalliance-1.0.jar

 

5.applicationContext.xml注意xml中和AOP相關的dtd的引入,還要注意pointcut="execution(* yourpackage.service.impl..*.*(..))" 的配置語法

 

6.最後在info.log裏面可以看到如上圖的輸出,最後再用shell統計即可。

 

參考:

http://jportal.iteye.com/blog/945725

 

http://www.java63.com/spring/configure_implement_aop.html

 

因爲對spring的aop不是很熟,在實現上有細節問題,在此記錄下!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章