一、引入aop依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
二、新建一个注解类
package com.example.demo.infra.annotations;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author 郑稳振
* @description: TODO
* @date 2021/11/26 11:17
*/
@Target(value= {ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Token {
}
Java除了内置了三种标准注解,还有四种元注解。
@Target 表示该注解用于什么地方,可能的值在枚举类 ElemenetType 中,包括:
ElemenetType.CONSTRUCTOR 构造器声明
ElemenetType.FIELD 域声明(包括 enum 实例)
ElemenetType.LOCAL_VARIABLE 局部变量声明
ElemenetType.METHOD 方法声明
ElemenetType.PACKAGE 包声明
ElemenetType.PARAMETER 参数声明
ElemenetType.TYPE 类,接口(包括注解类型)或enum声明
@Retention 表示在什么级别保存该注解信息。可选的参数值在枚举类型 RetentionPolicy 中,包括:
RetentionPolicy.SOURCE 注解将被编译器丢弃
RetentionPolicy.CLASS 注解在class文件中可用,但会被VM丢弃
RetentionPolicy.RUNTIME VM将在运行期也保留注释,因此可以通过反射机制读取注解的信息。
@Documented 将此注解包含在 javadoc 中 ,它代表着此注解会被javadoc工具提取成文档。在doc文档中的内容会因为此注解的信息内容不同而不同。相当与@see,@param 等。
@Inherited 允许子类继承父类中的注解。
三、新建一个切面类
在这里面可以实现注解的业务逻辑、比如权限校验等。
package com.example.demo.infra.Aspect;
import com.example.demo.infra.CommonException;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
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.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
/**
* @author 郑稳振
* @description: TODO
* @date 2021/11/26 11:23
*/
@Aspect
@Component
public class MyAspect {
public static final Logger logger = LoggerFactory.getLogger(MyAspect.class);
public static final String TOKEN_KEY = "token";
@Pointcut("@annotation(com.example.demo.infra.annotations.Token)")
public void annotationPointcut() {
}
@Before("annotationPointcut()")
public void beforePointcut(JoinPoint joinPoint) {
}
@Around("@annotation(com.example.demo.infra.annotations.Token)")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
logger.info("进入方法之前");
// 获取参数名称
String[] params = methodSignature.getParameterNames();
// 获取参数值
Object[] args = joinPoint.getArgs();
// 此处进入到方法前 可以实现一些业务逻辑
for(String s:params){
logger.info("params------------>{}",s);
}
for(Object object:args){
logger.info("object------------>{}",object);
}
try{
if(params.length!=0){
throw new CommonException("异常");
}
Object object = joinPoint.proceed();//执行方法,可以对传入参数进行修改
}catch (Exception e){
logger.info("{}",e.toString());
}
//logger.info("返回结果---》{}",object);
return ResponseEntity.ok("aop success!");//修改返回结果
}
/**
* 在切入点return内容之后切入内容(可以用来对处理返回值做一些加工处理)
* @param joinPoint
*/
@AfterReturning("annotationPointcut()")
public void doAfterReturning(JoinPoint joinPoint) {
logger.info("进入方法之后");
}
@AfterThrowing("annotationPointcut()")
private void afterThrowing() {
logger.info("抛异常了。。。。。");
}
}
四、测试controller
package com.example.demo.controller;
import com.example.demo.infra.annotations.Token;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
*@description: todo
*@author:郑稳振
*@Date : 2021/11/26:11:00
*/
@RestController
public class EasyExcelController {
@RequestMapping("/ano")
@Token
public ResponseEntity<String> login(String name, String pwd){
return ResponseEntity.ok("success!");
}
}