spring的IOC和AOP是說的最爛的東西,尤其是後者,給編碼帶來很多很多的方便,網上不上代碼都說了AOP主要用來做日誌記錄,異常處理,記錄程序執行時間,緩存這樣的事情,但是不少只是簡單的做一個說明,沒有代碼,這裏我把項目中實際使用的抽出來,本文主要是關於最簡單的日誌的記錄。
前提:需要對spring aop概念有所瞭解,以及有spring開發經驗,瞭解自定義註解。如果不明白,看下面的文章:
深入理解Java:註解(Annotation)自定義註解入門
-----------------------------------------------------------------------------------------------------------
下面進入正題:最終使用的效果如下:
@Service
public class TallyTypeService extends CrudService<TallyTypeDao, TallyType> {
.....
@LoggerPoint(pointKey=PointerKey.MONEY_TALLYTYPE)
public Page<TallyType> findPage(Page<TallyType> page, TallyType entity) {
return super.findPage(page,entity);
}
......
}
使用了自定義註解, LoggerPoint標明要記錄當前方法的執行參數,執行時間,執行類別等信息。pointKey是一個業務的分類。
/**
* 對於日誌注入點的功能說明枚舉.
* @author Administrator
*
*/
public enum PointerKey {
ALL("全部"), SINGLE("單接口"), UNKNOW("未知接口"), Test("測試"), MONEY_TALLYTYPE(
"金額類型");
private String name;
private PointerKey(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
對於LoggerPoint註解,很簡單:
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.METHOD })
public @interface LoggerPoint {
public PointerKey pointKey();
}
關鍵的是,使用解析上面註解的切面類:
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.renjie120.common.enums.PointerKey;
import com.renjie120.common.utils.JsonUtils;
import org.springframework.stereotype.Component;
@Component
@Aspect
public class LoggerAspect {
public static Logger logger = LoggerFactory.getLogger(LoggerAspect.class);
private Method getMethod(ProceedingJoinPoint pjp){
Signature signature = pjp.getSignature();
MethodSignature methodSignature = (MethodSignature) signature;
Method method = methodSignature.getMethod();
return method;
}
@Around("@annotation(com.renjie120.common.aspect.LoggerPoint)")
public Object trafficInterface(ProceedingJoinPoint pjp) throws Throwable {
Method method = this.getMethod(pjp);
LoggerPoint loggerPoint = method.getAnnotation(LoggerPoint.class);
PointerKey pointerKey = loggerPoint.pointKey();
Object[] args = pjp.getArgs();
Map<String,Object> paramMap = new HashMap<String,Object>();
for(Object arg:args){
paramMap.put(arg.getClass().getSimpleName(), arg);
}
String requestJson = JsonUtils.toJsonStr(paramMap);
String gid= UUID.randomUUID().toString();
System.out.println("請求參數:"+requestJson);
Object returnObj = null;
String errorMsg = null;
try {
System.out.println("當前執行:"+method.getName()+"---"+pointerKey.name()+",gid="+gid);returnObj = pjp.proceed();
return returnObj;
} catch (Exception e) {
errorMsg = ExceptionUtils.getStackTrace(e);
logger.error(e.getMessage(),e);
throw e;
} finally {
if (returnObj == null) {
returnObj = errorMsg;
}
System.out.println("響應:"+JsonUtils.toJsonStr(returnObj));
}
}
}
1、上面的註解@Component,@Aspect爲spring 註解,需要放在掃描路徑中:<context:component-scan base-package="com.renjie120" >
</context:component-scan>
2、上圖的@Around註解,標明使用的是環繞切面。<bean id="loggerAspect" class="com.renjie120.common.annotation.log.LoggerAspect" /> <aop:config> <aop:pointcut id="loginPointer" expression="@annotation(com.renjie120.common.annotation.log.LoggerPoint)" /> <aop:aspect id="aspect" ref="loggerAspect"> <aop:around method="trafficInterface" pointcut-ref="loginPointer" /> </aop:aspect> </aop:config>