项目中有些需求,比如方法异常上报、记录敏感操作等,这种需求就很适合使用注解完成。
1.引入依赖
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
<!--下面这个依赖和编写注解本身没有关系,只是在处理切面时使用到了里面的方法-->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.4</version>
</dependency>
2.编写注解
OperateTypeEnum:
package com.example.study.annotation;
public enum OperateTypeEnum {
CREATE(1, "新增"),
READ(2, "查询"),
UPDATE(3, "编辑"),
DELETE(4, "删除"),
IMPORT(5, "导入"),
EXPORT(6, "导出"),
CREATE_OR_UPDATE(7, "新增或编辑");
private Integer type;
private String desc;
OperateTypeEnum(Integer type, String desc) {
this.type = type;
this.desc = desc;
}
public Integer getType() {
return type;
}
public String getDesc() {
return desc;
}
}
OperateLog:
package com.example.study.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface OperateLog {
OperateTypeEnum value();
String desc();
}
OperateAspect:
package com.example.study.annotation;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
@Aspect
@Component
public class OperateAspect {
private static final String SEPARATOR = System.getProperty("line.separator");
@Pointcut("@annotation(com.example.study.annotation.OperateLog)")
private void pointCut() {
}
@Before("pointCut() && @annotation(operateLog)")
public void before(JoinPoint joinPoint, OperateLog operateLog) {
System.out.println("-----before");
}
@After("pointCut()")
public void after(JoinPoint joinPoint) {
System.out.println("-----after");
}
@AfterReturning(value = "pointCut()", returning = "result")
public void afterReturning(JoinPoint joinPoint, Object result) {
System.out.println("-----afterReturning");
System.out.println(result == null ? "null" : result.toString());
}
@AfterThrowing(value = "pointCut()", throwing = "e")
public void afterThrowing(JoinPoint joinPoint, Exception e) {
System.out.println("-----afterThrowing");
e.printStackTrace();
}
@Around("pointCut() && @annotation(operateLog)")
public Object saveOperateLog(ProceedingJoinPoint point, OperateLog operateLog) throws Throwable {
StringBuilder sb = new StringBuilder();
String methodName = point.getSignature().getName();
Object target = point.getTarget();
sb.append("调用方法名:").append(methodName)
.append(SEPARATOR).append("目标对象:").append(target.toString())
.append(SEPARATOR).append("方法参数:");
for (Object arg : point.getArgs()) {
sb.append(SEPARATOR).append(arg.toString());
}
System.out.println(sb.toString());
OperateTypeEnum operateType = operateLog.value();
if (operateType.equals(OperateTypeEnum.CREATE_OR_UPDATE)) {
for (Object arg : point.getArgs()) {
Field id;
try {
id = arg.getClass().getDeclaredField("id");
} catch (Exception e) {
continue;
}
Object idValue = null;
if (id != null) {
id.setAccessible(true);
idValue = id.get(arg);
}
if (idValue == null || StringUtils.isBlank(idValue.toString())) {
operateType = OperateTypeEnum.CREATE;
} else {
operateType = OperateTypeEnum.UPDATE;
}
break;
}
}
Object obj = point.proceed();
System.out.println("操作类型:" + operateType.getType() + "\t" + operateType.getDesc()
+ SEPARATOR + "操作描述:" + operateLog.desc());
return obj;
}
}