原文网址:Spring--AOP--获取注解信息(使用@Before)_IT利刃出鞘的博客-CSDN博客
简介
说明
本文介绍Spring(SpringBoot)的AOP的用法:自定义注解,在接口上使用此注解,然后在AOP中获得注解的相关信息。
本文使用@Before。
概述
因为AOP可以将切点设为注解类,因此,若想控制Controller,只需要控制@RequestMapping,即:
@Pointcut("@annotation(org.springframework.web.bind.annotation.RequestMapping)")
创建工程
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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.1.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>demo_SpringAOP</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>demo_SpringAOP</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.3</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
自定义注解类
package com.example.demo.annotation;
import java.lang.annotation.*;
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface OperationLog {
//操作的类型,添加,更新,删除
String type() default "add";
//操作描述
String desc() default "";
}
业务代码
Controller
package com.example.demo.controller;
import com.example.demo.annotation.OperationLog;
import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
@Api(tags = "用户")
@RequestMapping("/user")
@RestController
public class UserController {
@Autowired
UserService userService;
@ApiOperation("打印数据")
@GetMapping("print")
public User testPrint(User user) {
userService.printUser(user);
return user;
}
@ApiOperation("添加数据")
@PostMapping("add")
@OperationLog(type = "添加", desc = "添加数据")
public User testAdd(User user) {
return user;
}
@ApiOperation("更新数据")
@PostMapping("update")
@OperationLog(type = "更新", desc = "更新数据")
public User testUpdate(User user) {
userService.printUser(user);
return user;
}
}
Entity
package com.example.demo.entity;
import lombok.Data;
@Data
public class User {
private Integer id;
private String userName;
private String note;
}
Service
扫描二维码关注公众号,回复:
14388939 查看本文章
package com.example.demo.service;
import com.example.demo.entity.User;
public interface UserService {
public void printUser(User user);
}
package com.example.demo.service.impl;
import com.example.demo.entity.User;
import com.example.demo.service.UserService;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl implements UserService {
@Override
public void printUser(User user) {
if (user == null) {
throw new RuntimeException("检查用户参数是否为空");
}
System.out.print("id = " + user.getId());
System.out.print("\t userName = " + user.getUserName());
System.out.println("\t note = " + user.getNote());
}
}
启动类
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class DemoSpringaopSimpleApplication {
public static void main(String[] args) {
SpringApplication.run(DemoSpringaopSimpleApplication.class, args);
}
}
切面(核心)
@Around入参为ProceedingJoinPoint + 注解类,有返回值。这样就不用写@PointCut了,返回值会作为Controller数据返回回去。
package com.example.demo.aspect;
import com.example.demo.annotation.OperationLog;
import com.example.demo.entity.User;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
@Aspect
@Component
public class OperationLogAspect {
//有ProceedingJoinPoint和注解类,有返回值。这样就不用写@Pointcut了
@Around("@annotation(operationLog)")
public Object around2(ProceedingJoinPoint joinPoint, OperationLog operationLog) throws Throwable{
MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
Method method = methodSignature.getMethod();
System.out.println("joinPoint.getTarget().toString() : " + joinPoint.getTarget().toString());
System.out.println("methodSignature.getName() : " + methodSignature.getName());
System.out.println("method.getName() : " + method.getName());
System.out.println("method.getReturnType().getName() : " + method.getReturnType().getName());
System.out.println("-----------------------------------------------");
Object object = joinPoint.proceed();
System.out.println("method.getName(): " + method.getName());
System.out.print("type: " + operationLog.type());
System.out.println("\tdesc: " + operationLog.desc());
System.out.println("-----------------------------------------------");
Object[] objects = joinPoint.getArgs();
for (Object o : objects) {
System.out.println(o);
if (o instanceof User) {
System.out.println("id是:" + ((User)(o)).getId() +
"; 名字是:" + ((User)(o)).getUserName() +
"; 备注是:" + ((User)(o)).getNote());
}
}
return object;
}
}
测试
访问测试页面:http://localhost:8080/doc.html
测试1:添加
后端结果
------------------ 方法信息 ------------------
joinPoint.getTarget().toString() : com.example.demo.controller.UserController@4671b282
methodSignature.getName() : testAdd
method.getName() : testAdd
method.getReturnType().getName() : com.example.demo.entity.User
------------------ 注解数据 ------------------
type: 添加 desc: 添加数据
------------------ 入参数据 ------------------
User(id=123, userName=Tony, note=abc)
id是:123; 名字是:Tony; 备注是:abc
#################################################
测试2:更新
后端结果
------------------ 方法信息 ------------------
joinPoint.getTarget().toString() : com.example.demo.controller.UserController@4671b282
methodSignature.getName() : testUpdate
method.getName() : testUpdate
method.getReturnType().getName() : com.example.demo.entity.User
------------------ 注解数据 ------------------
type: 更新 desc: 更新数据
------------------ 入参数据 ------------------
User(id=1, userName=Pepper, note=2)
id是:1; 名字是:Pepper; 备注是:2
#################################################
id = 1 userName = Pepper note = 2