AOP的核心作用是:在程序运行期间,不修改代码的同时为程序增强功能。将必不可少的公共功能做成切面,随着程序运行切入到代码中运行。编写业务时只关注于核心功能 ,不再考虑事务、日志等公共功能,减轻了编码负担,更专注于业务
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface AnnotationTest {
// 日志注解说明
String value() default "";
// 日志类型 默认查询
ActionType actionType() default ActionType.QUERY;
}
public enum ActionType {
/**
* 查询
*/
QUERY,
/**
* 创建
*/
CREATE,
/**
* 修改
*/
MODIFY,
/**
* 删除
*/
REMOVE,
}
2.切面代码
@Aspect
@Component
public class AopAspect {
@Autowired
private AopAspectRepository aopAspectRepository;
// 切入点(自定义注解)
@Pointcut("@annotation(com.example.logintest.aop.AnnotationTest)")
public void AspectRun(){}
// 逻辑代码
@Around("AspectRun()")
public String aspectTest(ProceedingJoinPoint joinPoint) throws Throwable {
long start = System.currentTimeMillis();
//获取方法参数值数组
Object[] args = joinPoint.getArgs();
// 请求参数为
String requestParameters = JSONObject.toJSONString(args);
Object proceed = joinPoint.proceed();
// 响应参数
String responseParameters = JSONObject.toJSONString(proceed);
//得到其方法签名
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Method method = methodSignature.getMethod();
AnnotationTest annotation = method.getAnnotation(AnnotationTest.class);
// 注解描述
String value ="";
// 操作类型
String type ="";
if (Objects.nonNull(annotation)){
value = annotation.value();
type = annotation.actionType().name()
}
// 获取方法名
String methodSignatureName = methodSignature.getName();
// 获取请求类名
String className = joinPoint.getTarget().getClass().getName();
// 请求具体方法类名
String specificName = className+"."+methodSignatureName;
//获取方法参数类型数组
Class[] paramTypeArray = methodSignature.getParameterTypes();
String[] parameterNames = methodSignature.getParameterNames();
System.out.println("入参具体数据:");
for (int i = 0; i <paramTypeArray.length ; i++) {
System.out.println(parameterNames[i]+":"+args[i]+"["+paramTypeArray[i]+"]");
}
//动态修改其参数
//注意,如果调用joinPoint.proceed()方法,则修改的参数值不会生效,必须调用joinPoint.proceed(Object[] args)
String result = (String)joinPoint.proceed(args);
System.out.println("响应结果为:"+result);
long end = System.currentTimeMillis();
String time = String.valueOf((end - start));
LogEntity logEntity = new LogEntity(value,type,time,specificName,requestParameters,null,new Date());
aopAspectRepository.insert(logEntity);
//如果这里不返回result,则目标对象实际返回值会被置为null
return result;
}
@AfterThrowing("AspectRun()")
public void afterThrowing(){
System.out.println("已经报错了!!!");
}
}
3.保存到数据库
@Repository
public class AopAspectRepository {
@Autowired
private JdbcTemplate jdbcTemplate;
public void insert(LogEntity logEntity) {
String sql = "insert into t_log ( l_id, l_operation,l_action_type, l_response_time, l_method, l_params," +
" l_error_info, l_create_time) values(?,?,?,?,?,?,?,?)";
jdbcTemplate.update(sql,
logEntity.getId()
, logEntity.getOperation()
, logEntity.getActionType()
, logEntity.getResponseTime()
, logEntity.getMethod()
, logEntity.getParams()
, logEntity.getErrorInfo()
, logEntity.getCreateTime()
);
}
}
public class LogEntity {
/**
* 无参构造函数
*/
public LogEntity() {
}
public LogEntity( String operation, String actionType, String responseTime, String method, String params, String errorInfo, Date createTime) {
this.id = SnowFlake.instance().nextId();
this.operation = operation;
this.actionType = actionType;
this.responseTime = responseTime;
this.method = method;
this.params = params;
this.errorInfo = errorInfo;
this.createTime = createTime;
}
/**
* 主键
*/
private Long id;
/**
* 操作名称
*/
private String operation;
/**
* 操作类型
*/
private String actionType;
/**
* 响应时间
*/
private String responseTime;
/**
* 请求方法
*/
private String method;
/**
* 请求参数
*/
private String params;
/**
* 错误信息
*/
private String errorInfo;
/**
* 创建时间
*/
private Date createTime;
public Long getId() {
return id;
}
}
4.调用类
@RestController
public class AopAspectController {
@AnnotationTest("新增")
@GetMapping("/get")
public String add(String item,Integer code,Boolean status){
return item+"-这是响应参数";
}
}