一、基本概念

1、自定义注解

自定义注解我们必须了解四个元注解,什么是元注解?元注解指作用于注解之上的元数据或者元信息,简单通俗的讲,元注解就是注解的注解 .

Documented与Inherited是典型的标识性注解,也就是说在注解内部并没有成员变量,没有成员变量的注解称为标识注解

Documented

指明拥有这个注解的元素可以被javadoc此类的工具文档化。这种类型应该用于注解那些影响客户使用带注释的元素声明的类型。如果一种声明使用Documented进行注解,这种类型的注解被作为被标注的程序成员的公共API 。

Inherited

指明该注解类型被自动继承。如果用户在当前类中查询这个元注解类型并且当前类的声明中不包含这个元注解类型,那么也将自动查询当前类的父类是否存在Inherited元注解,这个动作将被重复执行知道这个标注类型被找到,或者是查询到顶层的父类。

具体请查看:https://blog.csdn.net/ab411919134/article/details/81252516

Retention

指明在什么级别显示此注解

Retention主要的参数类型包括以下几种:

RetentionPolicy.SOURCE 注解存在于源代码中,编译时会被抛弃

RetentionPolicy.CLASS 注解会被编译到class文件中,但是JVM会忽略

RetentionPolicy.RUNTIME JVM会读取注解,同时会保存到class文件中

Target

指明该类型的注解可以注解的程序元素的范围

Target主要的参数类型包括以下几种:

ElementType.TYPE 用于类,接口,枚举但不能是注解

ElementType.FIELD 作用于字段,包含枚举值

ElementType.METHOD 作用于方法,不包含构造方法

ElementType.PARAMETER 作用于方法的参数

ElementType.CONSTRUCTOR 作用于构造方法

ElementType.LOCAL_VERIABLE 作用于本地变量或者catch语句

ElementType.ANNOTATION_TYPE 作用于注解

ElementType.PACKAGE 作用于包

2、@ControllerAdvice 注解

在spring 3.2中,新增了@ControllerAdvice 注解,可以用于定义@ExceptionHandler、@InitBinder、@ModelAttribute,并应用到所有@RequestMapping中

二、完整示例

1、工程结构

2、pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <groupId>com.aop.demo</groupId>
<artifactId>aop-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.1.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--spring切面aop依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
</dependencies> </project>

3、新建启动类

package com.aop.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication; /**
* @author Administrator
* @date 2018/08/18
*/
@SpringBootApplication
public class Application {
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}

4、自定义异常类

package com.aop.demo.exception;

/**
* @author Administrator
* @date 2018/08/18
*/
public class OperateException extends RuntimeException{ public Integer errorCode;
public String errorMessage; public OperateException(Integer errorCode, String errorMessage){
this.errorCode = errorCode;
this.errorMessage = errorMessage;
} public Integer getErrorCode() {
return errorCode;
} public void setErrorCode(Integer errorCode) {
this.errorCode = errorCode;
} public String getErrorMessage() {
return errorMessage;
} public void setErrorMessage(String errorMessage) {
this.errorMessage = errorMessage;
}
}

5、自定义异常处理类,使用了@ControllerAdvice,来捕捉全局异常

package com.aop.demo.exception;

import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody; import java.util.HashMap;
import java.util.Map; /**
* @author Administrator
* @date 2018/08/18
*/
@ControllerAdvice
public class MyExceptionHandler {
@ExceptionHandler(value = Exception.class)
@ResponseBody
public Map<String,Object> exceptionProcess(Exception e){
Map<String,Object> map = new HashMap<String, Object>();
if(e instanceof OperateException){
OperateException myException = (OperateException) e;
System.out.println(myException.getErrorCode()+": "+ myException.getErrorMessage());
map.put(myException.getErrorCode().toString(),myException.getErrorMessage());
return map;
}else {
System.out.println("");
map.put("505","系统级错误");
return map;
}
}
}

6、引入aop来处理方法,执行前,执行中,执行后的动作。这里只是在控制台打印信息

1)定义了一个切入点:logwrite(),对com.aop.demo.controller里面的所有方法有效

举例说明execution表达式:

任意公共方法的执行:

execution(public * *(..))

任何一个以“set”开始的方法的执行:

execution(* set*(..))

AccountService 接口的任意方法的执行:

execution(* com.xyz.service.AccountService.*(..))

定义在service包里的任意方法的执行:

execution(* com.xyz.service.*.*(..))

定义在service包和所有子包里的任意类的任意方法的执行:

execution(* com.xyz.service..*.*(..))

定义在pointcutexp包和所有子包里的JoinPointObjP2类的任意方法的执行:

execution(* com.test.spring.aop.pointcutexp..JoinPointObjP2.*(..))")

package com.aop.demo.aspect;

import com.aop.demo.controller.MyController;
import com.aop.demo.exception.MyExceptionHandler;
import com.aop.demo.model.LogWrite;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method; /**
* @author Administrator
* @date 2018/08/20
*/
@Aspect
@Component
public class HttpAspect { @Autowired
private MyExceptionHandler myExceptionHandler; @Pointcut("execution(public * com.aop.demo.controller.*.*(..))")
public void logwrite(){ } @Before("logwrite()")
public void doBefore(JoinPoint joinPoint){
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
HttpServletRequest request = attributes.getRequest();
System.out.println("===========================以下是Aspect的Before方法的执行结果==========================");
//url
System.out.println("url="+request.getRequestURL());
//method
System.out.println("method="+request.getMethod());
//ip
System.out.println("id="+request.getRemoteAddr());
//获取类名和方法名
System.out.println("class_method="+joinPoint.getSignature().getDeclaringTypeName() + "," + joinPoint.getSignature().getName());
//args[]
System.out.println("args="+joinPoint.getArgs()); for (Method method: MyController.class.getDeclaredMethods()) {
if(method.getName().equals(joinPoint.getSignature().getName())){
LogWrite logWrite = method.getAnnotation(LogWrite.class);
if(logWrite!=null){
System.out.println("Found LogWrite:"+logWrite.user()+" "+logWrite.action() +"处理中");
}
}
}
} @Around("logwrite()")
public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
Object result = null;
try {
result = proceedingJoinPoint.proceed();
return result;
} catch (Exception e) {
System.out.println("===========================以下是Aspect的doAround方法捕捉到的异常==========================");
for (Method method: MyController.class.getDeclaredMethods()) {
if(method.getName().equals(proceedingJoinPoint.getSignature().getName())){
LogWrite logWrite = method.getAnnotation(LogWrite.class);
if(logWrite!=null){
System.out.println("Found LogWrite:"+logWrite.user()+" "+logWrite.action() +"处理失败");
}
}
}
return myExceptionHandler.exceptionProcess(e);
}
} @AfterReturning(pointcut = "logwrite()",returning = "object")//打印输出结果
public void doAfterReturing(JoinPoint joinPoint,Object object){
System.out.println("===========================以下是Aspect的doAfterReturing方法的执行结果==========================");
for (Method method: MyController.class.getDeclaredMethods()) {
if(method.getName().equals(joinPoint.getSignature().getName())){
LogWrite logWrite = method.getAnnotation(LogWrite.class);
if(logWrite!=null){
System.out.println("Found LogWrite:"+logWrite.user()+" "+logWrite.action() +"处理完成");
}
}
}
System.out.println("response="+object.toString());
}
}

7、自定义注解

package com.aop.demo.model;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; /**
* @author Administrator
* @date 2018/08/18
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LogWrite { public String user() default "adming"; public String action() default "create";
}

8、controller

package com.aop.demo.controller;

import com.aop.demo.exception.OperateException;
import com.aop.demo.model.LogWrite;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController; /**
* @author Administrator
* @date 2018/08/18
*/
@RestController
@RequestMapping("/test")
public class MyController { @RequestMapping(value = "/aopsuccess",method = RequestMethod.GET)
@LogWrite(user = "boshen",action = "excute aopsuccess")
public String testSucces(){
return "aopsuccess excute success";
} @RequestMapping(value = "/aoperror/{flag}",method = RequestMethod.GET)
@LogWrite(user = "boshen",action = "excute aoperror")
public String testError(@PathVariable String flag){
if(flag.equals("A")){
throw new OperateException(1001,"发生业务错误");
}
return "testError excute success";
}
}

说明:MyController类里面使用了自定义注解:@LogWrite,在HttpAspect 类里面,获取注解的内容得到user和action,打印到控制台上

9、用postman执行

控制台如下:

===========================以下是Aspect的Before方法的执行结果==========================
url=http://10.111.131.11:8084/aop-test/test/aopsuccess
method=GET
id=10.111.131.11
class_method=com.aop.demo.controller.MyController,testSucces
args=[Ljava.lang.Object;@3b3ffba0
Found LogWrite:boshen excute aopsuccess处理中
===========================以下是Aspect的doAfterReturing方法的执行结果==========================
Found LogWrite:boshen excute aopsuccess处理完成
response=aopsuccess excute success

控制台如下:

===========================以下是Aspect的Before方法的执行结果==========================
url=http://10.111.131.11:8084/aop-test/test/aoperror/A
method=GET
id=10.111.131.11
class_method=com.aop.demo.controller.MyController,testError
args=[Ljava.lang.Object;@67ca9239
Found LogWrite:boshen excute aoperror处理中
===========================以下是Aspect的doAround方法捕捉到的异常==========================
Found LogWrite:boshen excute aoperror处理失败
1001: 发生业务错误
===========================以下是Aspect的doAfterReturing方法的执行结果==========================
Found LogWrite:boshen excute aoperror处理完成
response={1001=发生业务错误}

springboot aop+@interface实现日志记录的更多相关文章

  1. springboot AOP全局拦截日志记录

    @Aspect@Component@Slf4jpublic class WebLogAspect { @Pointcut("execution(public * com.we.control ...

  2. SpringBoot AOP处理请求日志处理打印

    SpringBoot AOP处理请求日志处理打印 @Slf4j @Aspect @Configuration public class RequestAopConfig { @Autowired pr ...

  3. 在SpringBoot中用SpringAOP实现日志记录功能

    背景: 我需要在一个SpringBoot的项目中的每个controller加入一个日志记录,记录关于请求的一些信息. 代码类似于: logger.info(request.getRequestUrl( ...

  4. 【SpringBoot】13. logback日志记录

    logback日志记录 Spring Boot 1.5.19.RELEASE 1.导入相关jar包 在spring-boot-starter-web 中已经包含 2.添加logback.xml配置文件 ...

  5. spring aop 方法增加日志记录

    使用场景: 1:调用外部接口时需要记录出参和入参. 2:分布式系统之间,调用各个系统之间需要记录日志,一旦出现了问题也可以找得到元数据 一言不合,上代码: # 枚举类 package xxxxxxxx ...

  6. Springboot AOP写操作日志 GET POST

    pom.xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId> ...

  7. 使用SpringBoot AOP 记录操作日志、异常日志

    平时我们在做项目时经常需要对一些重要功能操作记录日志,方便以后跟踪是谁在操作此功能:我们在操作某些功能时也有可能会发生异常,但是每次发生异常要定位原因我们都要到服务器去查询日志才能找到,而且也不能对发 ...

  8. 从壹开始前后端分离【 .NET Core2.0 +Vue2.0 】框架之十 || AOP面向切面编程浅解析:简单日志记录 + 服务切面缓存

    代码已上传Github+Gitee,文末有地址 上回<从壹开始前后端分离[ .NET Core2.0 Api + Vue 2.0 + AOP + 分布式]框架之九 || 依赖注入IoC学习 + ...

  9. Z从壹开始前后端分离【 .NET Core2.0/3.0 +Vue2.0 】框架之十 || AOP面向切面编程浅解析:简单日志记录 + 服务切面缓存

    本文梯子 本文3.0版本文章 代码已上传Github+Gitee,文末有地址 大神反馈: 零.今天完成的深红色部分 一.AOP 之 实现日志记录(服务层) 1.定义服务接口与实现类 2.在API层中添 ...

随机推荐

  1. FortiGate基本信息

    1.介绍 FortiGate是全新的下一代防火墙,在整个硬件架构和系统上面都有新的设计,在性能和功能上面都有了很大提升,具有性能高.接口丰富.功能齐全.安全路由交换一体化.性价比高等优势. Forti ...

  2. sourceTree git的一些命令

    经常使用的三个命令 1.添加修改过的文件到缓冲区 git add. 2.commit到本地 git commit -am ' 更改描述' 3.如果是多人开发的话,中间可能会有别人先提交的这是就需要先把 ...

  3. C#中委托

    委托是一种安全地封装方法的类型,它与 C 和 C++ 中的函数指针类似.与 C 中的函数指针不同,委托是面向对象的.类型安全的和保险的.一个委托类型是代表与特定参数列表和返回类型的方法的引用类型.实例 ...

  4. 分享插件的使用加一个echart走数据

    html部分: <div class="topLink clearfix bdsharebuttonbox  bdshare-button-style0-16" data-b ...

  5. python学习笔记Day2

    字符编码 编程规范(PEP8) 变量1.常量(用大写) 2.变量 常用类型:str .int.float. long.bool 字串格式化: %d 整数 %2d占两位 %02d占两位用0填充 %f 浮 ...

  6. opencv 线,椭圆 圆

    //void MyLines() { // Point p1 = Point(20, 30); // Point p2; // p2.x = 400; // p2.y = 400; // Scalar ...

  7. 探索未知种族之osg类生物---呼吸分解之事件循环三

    那我们就开始处理这些事件中得到的所有的交互事件,首先我们要判断这些事件是否包含osg的退出事件,那什么情况下会触发这个退出事件呢?如果您运行过osg中example中的小例子的,聪明的你一定就会发现当 ...

  8. *jQuery选择器总结(原创:最全、最系统、实例展示)

    jquery选择器包括四部分:一.基本选择器二.层次选择器三.过滤选择器四.表单元素选择器 一.基本选择器1.ID选择器:$('#myDiv');2.类选择器:$('.className');3.元素 ...

  9. ROC曲线 Receiver Operating Characteristic

    ROC曲线与AUC值   本文根据以下文章整理而成,链接: (1)http://blog.csdn.net/ice110956/article/details/20288239 (2)http://b ...

  10. 洛谷1984 [SDOI2008]烧水问题

    一道找规律 原题链接 显然要将烧得的温度最大化利用,即每次都去热传递. 设水沸腾为\(x\). 第一杯直接烧水,需提高\(x\). 第二杯先与第一杯进行热传递,这样只需提高\(\dfrac{x}{2} ...