欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

AOP实践-日志记录

程序员文章站 2022-04-25 20:09:03
...

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)
相关标签: AOP