一、基本概念

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. Hive和并行数据仓库的比较

    最近分析和比较了Hive和并行数据仓库的架构,本文记下一些体会. Hive是架构在Hadoop MapReduce Framework之上的开源数据分析系统. Hive具有如下特点: 1. 数据以HD ...

  2. Aria2GUI 导出下载 刷新界面,任务消失

    问题1. 2.勾选之后 导出下载 没了,神烦 解决方法解决方法1.点击分享, 2.创建链接 3.然后复制链接到网站,  下面是 下载 工具和 谷歌插件http://www.sdifen.com/ari ...

  3. 数字&字符串

    一.数字 数字分为整型(int)和浮点型(float) int(整型):整数数字 >>> a = 12 >>> a 12 >>> b = 12.3 ...

  4. spring+quartz报错:Table 'XXXX.QRTZ_TRIGGERS' doesn't exist

    Spring4.3.4 + quartz2.2.1配置到application.xml中 <properties> <spring.version>4.3.4.RELEASE& ...

  5. 为什么使用Reazor

    原因:类似于前边写的模板页,自己写了.还需要用replace来替换成自己想要的变量.. 常见的模板引擎:Razor.Nvelocity.Vtemplate. Razor有VS自动提示,而且有助于学习a ...

  6. [z]一步步教你如何在 Visual Studio 2013 上使用 Github

    [z]http://www.admin10000.com/document/4004.html 介绍 我承认越是能将事情变简单的工具我越会更多地使用它.尽管我已经知道了足够的命令来使用Github,但 ...

  7. IDEA 的 Edit 设置

    1.设置鼠标悬浮提示 General -- Show quick documentation on mouse move 2.自动导包 3.设置显示行号和方法的间隔符 4.忽略大小写  4.设置取消单 ...

  8. geoserver 发布无坐标png

    1.geoserver 安装一些插件的时候,直接去http://docs.geoserver.org/ 官网,选择自己geoserver对应的版本的插件就可以了. 2.geoserver 发布自身带有 ...

  9. VS2010错误

    1.用VS2010生成C++程序时,链接器工具错误 LNK1123: fatal error LNK1123: failure during conversion to COFF: file inva ...

  10. 在 Ubuntu 上使用微信客户端

    原文地址: http://www.myzaker.com/article/5979115d1bc8e08c30000071/ 在这个快速信息交互时代,无论是工作还是生活,都需要频繁的网络社交,而在中国 ...