package com.shhxzq.fin.lifeapp.biz.utils; import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.net.InetAddress; import java.text.MessageFormat; import java.util.HashMap; import java.util.Map; import java.util.concurrent.Callable; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.Signature; import org.aspectj.lang.reflect.MethodSignature; import com.shhxzq.fin.lifeapp.biz.service.RabbitService; import com.shhxzq.fin.lifeapp.model.base.BaseUuidLogger; import com.shhxzq.fin.lifeapp.model.base.BusinessException; import com.shhxzq.fin.lifeapp.model.base.LogMethodTime; import com.shhxzq.fin.lifeapp.model.base.MonitorMethodTypeEnum; import com.shhxzq.fin.lifeapp.model.base.SystemEnum; /** * 服务层AOP * @author Gxx */ public class ServiceAop { /** * 日志记录器 */ Logger logger = BaseUuidLoggerUtils.getBaseUuidLogger(); /** * 方法前后操作 * @param pjp * @return * @throws Exception */ public Object around(ProceedingJoinPoint pjp) throws Throwable { /** * 获取切面方法 */ Signature sig = pjp.getSignature(); MethodSignature msig = null; if (!(sig instanceof MethodSignature)) { throw new IllegalArgumentException("该注解只能用于方法"); } msig = (MethodSignature) sig; Object target = pjp.getTarget(); Method currentMethod = target.getClass().getMethod(msig.getName(), msig.getParameterTypes()); /** * 判断是否有Logger对象,有则强制设置为BaseUuidLogger */ Field[] files = target.getClass().getDeclaredFields(); for(Field field : files) { if(field.getType() == Logger.class) { /** * 私有变量必须先设置Accessible为true */ field.setAccessible(true); /** * 判断是否第一次赋值 */ if(!(field.get(target) instanceof BaseUuidLogger)) { /** * 创建基础日志操作实体-同一个线程的uuid是一样的 */ BaseUuidLogger uuidLogger = new BaseUuidLogger(); /** * 拷贝属性-父类向子类拷贝(两层父类) */ BeanUtils.copyPropertiesLevel2(uuidLogger, field.get(target)); /** * 覆盖设置Logger对象 */ field.set(target, uuidLogger); } } } /** * 判断是否加注解@LogMethodTime 和 是否落地 */ boolean isLogMethodTime = currentMethod.isAnnotationPresent(LogMethodTime.class);//是否加注解@LogMethodTime boolean isMonitor = false;//是否监控 MonitorMethodTypeEnum monitorMethodType = null;//监控方法类型枚举 SystemEnum outerSystem = null;//外部系统代码 String methodName = null;//方法名称 String resv1 = null;//备注字段1 String resv2 = null;//备注字段2 String resv3 = null;//备注字段3 /** * 判断是否加注解@LogMethodTime */ if(isLogMethodTime) { Annotation p = currentMethod.getAnnotation(LogMethodTime.class); Method m = p.getClass().getDeclaredMethod("isMonitor", null); isMonitor = (boolean) m.invoke(p, null); /** * 判断是否监控 */ if(isMonitor) { m = p.getClass().getDeclaredMethod("monitorMethodType", null); monitorMethodType = (MonitorMethodTypeEnum) m.invoke(p, null); m = p.getClass().getDeclaredMethod("outerSystem", null); outerSystem = (SystemEnum) m.invoke(p, null); m = p.getClass().getDeclaredMethod("methodName", null); methodName = (String) m.invoke(p, null); m = p.getClass().getDeclaredMethod("resv1", null); resv1 = (String) m.invoke(p, null); m = p.getClass().getDeclaredMethod("resv2", null); resv2 = (String) m.invoke(p, null); m = p.getClass().getDeclaredMethod("resv3", null); resv3 = (String) m.invoke(p, null); } } /** * 类.方法 名字 */ String targetName = pjp.getTarget().getClass().getName() + "." + pjp.getSignature().getName(); String request = StringUtils.EMPTY; String response = StringUtils.EMPTY; /** * 判断是否加注解@LogMethodTime */ if(isLogMethodTime) { request = BeAopUtil.getStringFromRequest(pjp.getArgs()); String requestMsg = "log - {0} request - {1}"; logger.info(MessageFormat.format(requestMsg, new Object[] { targetName, request })); } /** * 开始时间 结束时间 耗时 是否异常发生 */ long begin = DateUtils.getNow().getTime(); long end = 0; long usedTime = 0; boolean isException = false; Object result = null; try { /** * 执行方法 */ result = pjp.proceed(); /** * 返回信息 */ response = BeAopUtil.getStringFromResponse(result); /** * 返回结果 */ return result; } catch (BusinessException t) { logger.error(targetName + " exception occure!reason:" + t.getMessage()); /** * 异常发生,返回报文为异常信息 */ isException = true; response = t.getMessage(); throw t; } catch (Throwable t) { logger.error(targetName + " exception occure!", t); /** * 异常发生,返回报文为异常信息 */ isException = true; response = t.getMessage(); throw t; } finally { try { /** * 注解@LogMethodTime才计算计算时间 */ if(isLogMethodTime) { end = DateUtils.getNow().getTime(); usedTime = end - begin; logger.info(targetName + " use time : " + usedTime / 1000.0 + "s"); /** * 没有异常发生,打印返回信息 */ if(!isException) { String responseMsg = "log - {0} response - {1}"; logger.info(MessageFormat.format(responseMsg, new Object[] { targetName, response })); } /** * 判断是否监控 */ if(isMonitor) { /** * 获取本地ip */ String localIP = StringUtils.EMPTY; try { InetAddress localHost = InetAddress.getLocalHost(); localIP = localHost.getHostAddress(); } catch (Exception e) { logger.error("获取本地ip异常发生", e); } /** * 获取方法路径(包括参数类型) */ String methodRoute = TransMonitorUtils.getMethodRoute(targetName, pjp.getArgs()); /** * 组织map */ Map map = new HashMap(); map.put("methodType", monitorMethodType == null ? StringUtils.EMPTY : monitorMethodType.getType());//方法类型 map.put("outerSystem", outerSystem == null ? StringUtils.EMPTY : outerSystem.getSystem());//外部系统代码 map.put("methodRoute", methodRoute);//方法路径 map.put("methodName", methodName);//方法名称 map.put("request", BaseUuidLogger.uuid.get() + request);//入参 map.put("response", response);//出参 map.put("isException", isException);//是否异常发生 map.put("beginTime", begin);//开始时间 map.put("endTime", end);//结束时间 map.put("usedTime", usedTime);//耗时(毫秒) map.put("ip", localIP);//本地ip /** * 从ThreadLocal中MAP获取resv1,2,3 * 优先级高于 * 从注解中解析表达式获取对象 */ String resv1InMap = TransMonitorUtils.getResv1(methodRoute);//从ThreadLocal中MAP获取备注字段1 String resv2InMap = TransMonitorUtils.getResv2(methodRoute);//从ThreadLocal中MAP获取备注字段2 String resv3InMap = TransMonitorUtils.getResv3(methodRoute);//从ThreadLocal中MAP获取备注字段3 if(null != resv1InMap) { map.put("resv1", resv1InMap); } else { map.put("resv1", ExpressLanUtils.getObjectFromExpressexToString(resv1, pjp.getArgs(), result, isException));//从注解中解析表达式获取对象-备注字段1 } if(null != resv2InMap) { map.put("resv2", resv2InMap); } else { map.put("resv2", ExpressLanUtils.getObjectFromExpressexToString(resv2, pjp.getArgs(), result, isException));//从注解中解析表达式获取对象-备注字段2 } if(null != resv3InMap) { map.put("resv3", resv3InMap); } else { map.put("resv3", ExpressLanUtils.getObjectFromExpressexToString(resv3, pjp.getArgs(), result, isException));//从注解中解析表达式获取对象-备注字段3 } /** * 异步执行任务-提交任务 */ AsynUtils.getInstance().submitTask(new Callable() { @Override public Boolean call() throws Exception { /** * 推送la交易监控(为了异步执行) */ SpringUtils.getInstance().getBean(RabbitService.class).sendLaTransMonitor(map); return true; } }); } } } catch (Exception e) { logger.error("切面处理异常发生!", e); } } } }