AOP實現方法的日誌記錄,並輸出到指定文件

     實現背景:需要對service中各個方法進行日誌記錄,包括執行時間,方法用途,以及方法執行結果等。從而知道每個方法對數據庫的改動以及影響。

爲了實現對每個方法用途的記錄,定義了一個註解,然後在註解中存放了方法的用途信息。

定義註解:

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ServiceLogAnnotation {
	public String value();
}

   定義AOP advisor:關於@Pointcut的用法請參見這裏

@Component
@Aspect
public class ServiceLogAdvisor{
	SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	@Autowired
	HttpServletRequest httpServletRequest;
	
	@Pointcut("execution(* com.test..*.*(..))")
	public void advisorMethod(){
		
	}
	
// 方法執行完後執行,在配置目錄下以及使用了規定的註解的方法有效
	@AfterReturning(returning="result",value="advisorMethod() && @annotation(log)")
	public void after(JoinPoint joinPoint,ServiceLogAnnotation log,Object result){
		// 方法名稱
		String methodName = joinPoint.getSignature().getName();
		// 方法參數
		Object[] args = joinPoint.getArgs(); 
		
		MethodSignature methodSignature = (MethodSignature)joinPoint.getSignature();    
		String[] parameters = methodSignature.getParameterNames();
		
		String userId = "";
		String userName = "";
		try {
// 在session中獲取登錄信息
			// 用戶信息
			HttpSession session = httpServletRequest.getSession();

			// 獲取管理員ID和管理員名字
			userId = (String) session.getAttribute("USERID");
			userName = (String) session.getAttribute("USERNAME");
		} catch (Exception e) {
			userId = "001";
			userName = "系統";
			e.printStackTrace();
		}
		
// 使用自定義的日誌類(ServiceLog)進行記錄,關於自定義日誌類參見:http://blog.csdn.net/qq_25610165/article/details/70946077
		ServiceLog.serviceLogger("調用方法:"+ methodName);
		ServiceLog.serviceLogger("方法簽名:" + joinPoint.getSignature());
		ServiceLog.serviceLogger("操作人ID:" + userId);
		ServiceLog.serviceLogger("操作人姓名:" + userName);
		ServiceLog.serviceLogger("方法用途:" + log.value());
		ServiceLog.serviceLogger("接收參數:");
		
		for(int i = 0; i < args.length; i++){
			ServiceLog.serviceLogger(parameters[i] + ":" + args[i]);
		}
		ServiceLog.serviceLogger("返回結果:");
		if(result instanceof Map){
			Map<String,Object> map = (Map<String,Object>)result;
			ArrayList objects = (ArrayList)map.get("rows");
			for(Object object : objects){
				ServiceLog.serviceLogger(object.toString());
			}
		}else if(result instanceof List){
			for(int i = 0; i < ((List)result).size(); i++){
				String mapMessage = "";
				for (Map.Entry<String, Object> entry : ((Map<String,Object>)((List) result).get(i)).entrySet()) {  
					mapMessage += entry.getKey() + " = " + entry.getValue() + "\t";
				}  
				 ServiceLog.serviceLogger(mapMessage);
			}
		}else{
			ServiceLog.serviceLogger(result);
		}
		ServiceLog.serviceLogger("方法結束時間:" + sdf.format(new Date()));
	}
}

在Spring 上下文中配置AOP(applicationContext.xml)

 	<!-- AOP配置 -->
   	<bean id="ServiceAdvisor" class="com.cisdi.tool.serviceLog.ServiceLogAdvisor"></bean>
   	<aop:aspectj-autoproxy proxy-target-class="true" />
使用:AOP的實現,使用了動態代理模式,只能對public 方法生效,具體使用如下

 

@ServiceLogAnnotation("測試")
	public void test(){
		
	}

只需要在需要使用的方法上,添加上自定義註解即可,同時該類應該存放在ServiceLogAdvisor中@Pointcut中定義的目錄下。

關於自定義的日誌類,請參見作者的另一篇文章《log4j自定義級別並輸出到指定文件


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