haidaoxianzi 2017-09-13
spring的IOC和AOP是说的最烂的东西,尤其是后者,给编码带来很多很多的方便,网上不上代码都说了AOP主要用来做日志记录,异常处理,记录程序执行时间,缓存这样的事情,但是不少只是简单的做一个说明,没有代码,这里我把项目中实际使用的抽出来,本文主要是关于最简单的日志的记录。
前提:需要对spring aop概念有所了解,以及有spring开发经验,了解自定义注解。如果不明白,看下面的文章:
Spring思维导图,让Spring不再难懂(aop篇)
深入理解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 注解,需要放在扫描路径中: