RuoYI-Vue-PLUS中的注解以及自定义注释的实现(AOP)
什么是注解;注解的原理是什么?若依中的注解说明
干货版本
自定一个每次调用方法都输出 好好学习天天向上的 注解
在Java中,你可以通过自定义注解和使用AOP(面向切面编程)来实现这个需求。以下是一个简单的示例:
首先,定义一个自定义注解:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.METHOD) // 表示该注解只能用于方法上
@Retention(RetentionPolicy.RUNTIME) // 表示注解信息在运行时可以获取
public @interface StudyReminder {
}
然后,使用Spring AOP或其他支持AOP的框架,创建一个切面类来处理这个注解:
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class StudyReminderAspect {
@Around("@annotation(StudyReminder)")
public Object logStudyMessage(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("好好学习天天向上");
return joinPoint.proceed(); // 执行原方法
}
}
现在,你可以在任何方法上使用@StudyReminder注解,每次调用该方法时,都会先输出“好好学习天天向上”的提示:
罗里吧嗦版本
SpringBoot支持我们开发者能够自定义注解,从而实现一些项目中遇到的特定问题,这个功能不知道用过的小伙伴们多不多,反正我是用得不多,但是使用之后就会发现,实在是太便捷了,配合上AOP,简直是开发的大救星,这边就简单的介绍利用SpringBoot自定义注解来实现日志的收集和问题的监控功能。
在项目的开发中,日志的打印与收集整理一向是一件十分重要的事,可以毫不夸张的说,如果日志信息详细合理,对于我们后期定位bug,修复功能起着事倍功半的作用,但是打印日志也是一件繁琐的事情,一是有很多日志是属于重复日志,基本每个方法都要打印,写起来就是冗余代码;二来本来流畅的代码,前边加一条日志打印,后边加一条日志打印,读起来感受不是很好;三来打印日志本来就不影响代码功能的实现,有些小伙伴因为时间急给漏了,忘了也是很常有的事,所以如果能够让每个方法自动生成关键的日志信息,然后存储到数据中,那么不仅能够节省开发时间,提高开发效率,也能让我们的代码显得更加简洁明了。
利用SpringBoot中的自定义注解加上AOP就可以轻松的帮助我们实现上面说的功能,话不多说,直接上干货——代码:
定义
一、首先需要定义一个注解的interface,也就是我们自定义注解的注解名,同时也要定义里面的内部参数
在SpringBoot中,有四个元注解[详见附录A],它们被称为注解的注解,我们在自定义注解的时候,就会用到它们,下面对他们分别做个简单的介绍:
@Target:这个注解就是规定了我们自定义的注解所使用的的范围,里面有个属性叫ElementType,关于这个属性有着很多值:
@Retention:这个注解规定了我们自定义注解的生命周期,里面有个属性叫RetentionPolicy,关于这个属性有三个值:
@Inherited:这个注解是一个标记注解,表明被标注的类型是可以被继承的。
@Documented:该注解表明被注解信息是否被添加在Javadoc中。
实体类
二、定义完自定义的注解接口后,接下来就是要定义相对应的实体类了,我们这里实现的功能是对每个方法的执行结果进行日志的记录,既然是记录,那肯定是要落库的,这样才能方便日后的查看,否则这些记录就没有太大的意义,因此要定义一个日志的实体类,作为持久化对象。
切面逻辑
三、定义完实体对象后,接下来就是要写切面逻辑,在逻辑里实现对方法输出结果的捕获与处理,持久化。我们知道一个方法的输出结果无非是两种,一个是方法执行成功,输出正确的结果;一个是方法执行失败,中途报错。对于这两种不同的执行结果,分别都需要用不同的逻辑来进行处理。
1.方法执行成功,输出正确的结果:
@AfterReturning(value="xxx()", returning = "returnValue")
public void writeCrmLog(JoinPoint joinPoint, Object returnValue) throws Exception{
/**获取相对应的方法参数,存入数据库中*/
........
}
2.方法执行失败,中途报错:
@AfterReturning(value="xxx()", throwing= "ex")
public void throwingExCrmLog(JoinPoint joinPoint, Object returnValue) throws Exception{
/**获取相对应的方法参数,存入数据库中*/
........
}
测试
四、利用切面实现的方法操作日志的记录,既简化了代码,提高了开发效率,又减少了日记的遗漏,规范了日记格式,对于后续定位问题提供了更方便快捷的方式,可谓是一举多得,是开发代码中不可或缺的重要组成部分。
@GetMapping
@GetMapping是@RequestMapping(method = RequestMethod.GET)缩写的组合注解,用于将 HTTP 的get 请求映射到特定处理程序的方法注解。
@GetMapping就是@RequestMapping附加了get请求方法。也就是说@GetMapping就是一个只能用来处理http的get请求的注解,比较专一,只能干这一件事,不像@RequestMapping可以处理多种http的请求。
在一般情况下我们开发可能都是用@RequestMapping(method=RequestMethod.×××),因为@RequestMapping可以直接替代以上两个注解,但是以上两个注解并不能替代@RequestMapping。
类似的组合注解还有上面提到的:@PutMapping、@DeleteMapping、@PatchMapping三个注解
@PostMapping
@DeleteMapping
@Validated
@RequiredArgsConstructor
生成带有必需参数的构造函数。 必需的参数是最终字段和具有约束的字段,例如@NonNull 。
完整的文档可在@lconstructor的项目lombok功能页面上找到 。即使未列出,该注释也具有onConstructor参数。 有关更多详细信息,请参见完整的文档。
这个是基于lombok的使用时必须导入lombok包。
@RestController
@RepeatSubmit
参考文档:https://blog.csdn.net/Michelle_Zhong/article/details/125004718
@Repeatsubmit注解是Spring框架提供的用于防止表单重复提交的注解
附录A
@Target:这个注解就是规定了我们自定义的注解所使用的的范围,里面有个属性叫ElementType,关于这个属性有着很多值:
ElementType.TYPE 类,接口(包括注解类型),enum声明
ElementType.FIELD 字段声明(包括枚举常量)
ElementType.METHOD 方法
ElementType.PARAMETER 参数
ElementType.CONSTRUCTOR 构造器
ElementType.LOCAL_VARIABLE 局部变量
ElementType.ANNOTATION_TYPE 注解类型
ElementType.PACKAGE 包
ElementType.TYPE_PARAMETER 类型参数
ElementType.TYPE_USE 类型的注解,如泛型
@Retention:这个注解规定了我们自定义注解的生命周期,里面有个属性叫RetentionPolicy,关于这个属性有三个值:
RetentionPolicy.SOURCE 编译后即丢弃,自定义注解在编译结束后就不再产生意义,因此不会写入到Class文件中
RetentionPolicy.CLASS 类加载时丢弃,编译后保留(在Class文件中存在,但是JVM运行时将会忽略),默认使用这种方式
RetentionPolicy.RUNTIME 运行期保留,在Class文件中存在,JVM运行时保留,可以通过反射机制读取该注解的信息
@Inherited:这个注解是一个标记注解,表明被标注的类型是可以被继承的。
@Documented:该注解表明被注解信息是否被添加在Javadoc中。