1. 程式人生 > >AOP實踐-日誌記錄

AOP實踐-日誌記錄

AOP實踐-自定義註解實現日誌記錄 專案環境springboot spring AOP預設是使用AspectJ的註解 https://www.eclipse.org/aspectj/

1.引入jar包

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>

2.自定義註解

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MethodLog {
	String remark() default "";
	
	int operType() default 0;
}

3.日誌記錄 此處每次操作完成之後記錄日誌

@Component
@Aspect
public class LogService {
	@Autowired
	OperateLogMapper operateLogMapper;
	
	/**
	 * 切點
	 */
	@Pointcut("@annotation(com.cmft.basic.aspect.annotation.MethodLog)")
	public void methodCachePointcut() {
	}
	
	@AfterThrowing("methodCachePointcut()")
	public void test(JoinPoint point) {
	}
	
	/**
	 * 切面
	 *
	 * @param point
	 * @return
	 * @throws Throwable
	 */
	@AfterReturning("methodCachePointcut()")
	public void recordOperateLog(JoinPoint point) throws Throwable {
		Map<String, Object> methodMap = getMthodMap(point);
		String packages = point.getThis().getClass().getName();
		if (packages.indexOf("$$EnhancerByCGLIB$$") > -1) { // 如果是CGLIB動態生成的類
			packages = packages.substring(0, packages.indexOf("$$"));
			return;
		}
		Object[] methodParam = null;
		methodParam = point.getArgs(); // 獲取方法引數
		Map<String, Object> parMap = objectToMap(methodParam[0]);
		// 記錄日誌
		//...
		operateLog.setRemark(String.valueOf(methodMap.get("remark")));
		operateLog.setTypeId((Integer)methodMap.get("operType"));
		//...
	}
	
	/**
	 * 獲取利用反射獲取類裡面的值和名稱
	 *
	 * @param obj
	 * @return
	 * @throws IllegalAccessException
	 */
	public static Map<String, Object> objectToMap(Object obj) throws IllegalAccessException {
		Map<String, Object> map = new HashMap<>();
		Class<?> clazz = obj.getClass();
		if (clazz.isPrimitive() || clazz.getName().equals("java.lang.String")) {
			map.put("id", obj);
			return map;
		}
		for (Field field : clazz.getDeclaredFields()) {
			field.setAccessible(true);
			String fieldName = field.getName();
			Object value = field.get(obj);
			map.put(fieldName, value);
		}
		return map;
	}
	
	/**
	 * 獲取方法中的中文備註
	 *
	 * @param joinPoint
	 * @return
	 * @throws Exception
	 */
	public static Map<String, Object> getMthodMap(JoinPoint joinPoint) throws Exception {
		String targetName = joinPoint.getTarget().getClass().getName();
		String methodName = joinPoint.getSignature().getName();
		Object[] arguments = joinPoint.getArgs();
		Class<?> targetClass = Class.forName(targetName);
		Method[] method = targetClass.getMethods();
		Map<String, Object> methodMap = new HashMap<String, Object>();
		for (Method m : method) {
			if (m.getName().equals(methodName)) {
				@SuppressWarnings("rawtypes")
				Class[] tmpCs = m.getParameterTypes();
				if (tmpCs.length == arguments.length) {
					MethodLog methodCache = m.getAnnotation(MethodLog.class);
					if (methodCache != null) {
						int operType = methodCache.operType();
						String remark = methodCache.remark();
						methodMap.put("operType", operType);
						methodMap.put("remark", remark);
					}
					break;
				}
			}
		}
		return methodMap;
	}
}

4.使用 AOP必須基於介面實現,所以在介面實現類的方法上加入如下註解即可

@MethodLog(remark = "更新", operType = Constant.APPROVE)