自定义注解
| package com.example.servlet; |
| |
| import javax.validation.Payload; |
| 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 MySysLog { |
| |
| String decipher(); |
| |
| int length(); |
| |
| |
| |
| |
| |
| String[] paramValues(); |
| |
| |
| |
| |
| String message() default "参数不为指定值"; |
| |
| Class<?>[] groups() default {}; |
| |
| Class<? extends Payload>[] payload() default {}; |
| } |
| |
注解解释
@Target
-
该注解用于@Check注解上,可以表明Check注解的使用位置,下面是Target中的ElementType
的释义
-
| 当@Target中的参数为那个字段时,表明这个注解只能使用在什么位置 |
| ElementType.TYPE:说明该注解只能被声明在一个类前。 |
| ElementType.FIELD:说明该注解只能被声明在一个类的字段前。 |
| ElementType.METHOD:说明该注解只能被声明在一个类的方法前。 |
| ElementType.PARAMETER:说明该注解只能被声明在一个方法参数前。 |
| ElementType.CONSTRUCTOR:说明该注解只能声明在一个类的构造方法前。 |
| ElementType.LOCAL_VARIABLE:说明该注解只能声明在一个局部变量前。 |
| ElementType.ANNOTATION_TYPE:说明该注解只能声明在一个注解类型前。 |
| ElementType.PACKAGE:说明该注解只能声明在一个包名前 |
@Retention
-
该注解用于@Check注解上,可以表明Check注解的生命周期,下面是Retention中RetentionPolicy
的释义
-
| 当@Retention中的参数为那个字段时,表明这个注解的可用范围 |
| RetentionPolicy.SOURCE: 注解只保留在源文件中 |
| RetentionPolicy.CLASS : 注解保留在class文件中,在加载到JVM虚拟机时丢弃 |
| RetentionPolicy.RUNTIME: 注解保留在程序运行期间,此时可以通过反射获得定义在某个类上的所有注解。 |
AOP切面
| import org.aspectj.lang.ProceedingJoinPoint; |
| import org.aspectj.lang.annotation.Around; |
| import org.aspectj.lang.annotation.Aspect; |
| import org.aspectj.lang.reflect.MethodSignature; |
| import org.springframework.stereotype.Component; |
| |
| import com.example.demo.annotation.MySysLog; |
| |
| import lombok.extern.slf4j.Slf4j; |
| |
| |
| |
| |
| |
| @Slf4j |
| @Aspect |
| @Component |
| public class SystemLogAspect { |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| @Around("@annotation(mySysLog)") |
| public Object around(ProceedingJoinPoint point, MySysLog mySysLog) throws Throwable { |
| |
| MethodSignature signature = (MethodSignature)point.getSignature(); |
| MySysLog annotation = signature.getMethod().getAnnotation(MySysLog.class); |
| String decipher = annotation.decipher(); |
| int length = annotation.length(); |
| System.out.println("获取注解上传入的参数: "+decipher +" "+length); |
| |
| |
| |
| |
| |
| String name = point.getTarget().getClass().getName(); |
| System.out.println("被切面的类相对路径: "+name); |
| |
| String name1 = signature.getName(); |
| System.out.println("被切面的类名: "+name1); |
| |
| Object[] args = point.getArgs(); |
| System.out.println("切面传入的参数:"+args); |
| |
| return point.proceed(); |
| |
| } |
| |
| } |
测试注解和AOP
Controller
| import com.example.demo.annotation.MySysLog; |
| import org.springframework.web.bind.annotation.PostMapping; |
| import org.springframework.web.bind.annotation.RequestBody; |
| import org.springframework.web.bind.annotation.RequestMapping; |
| import org.springframework.web.bind.annotation.RestController; |
| |
| |
| |
| |
| |
| @RequestMapping("logAspect") |
| @RestController |
| public class MySystemLogAspectController { |
| |
| @MySysLog(decipher = "ChenQ",length = 28) |
| @PostMapping("test") |
| public void MySystemLogAspectControllerTest(@RequestBody UserAspectTest userAspectTest){ |
| |
| System.out.println(userAspectTest); |
| } |
| |
| |
| } |
实体类
| import lombok.EqualsAndHashCode; |
| import lombok.Getter; |
| import lombok.Setter; |
| |
| |
| |
| |
| |
| @Getter |
| @Setter |
| @EqualsAndHashCode |
| public class UserAspectTest { |
| |
| private String name; |
| |
| private String age; |
| } |
输出结果

tips
| package com.example.demo.annotation; |
| |
| import java.lang.annotation.ElementType; |
| import java.lang.annotation.Retention; |
| import java.lang.annotation.RetentionPolicy; |
| import java.lang.annotation.Target; |
| |
| |
| |
| |
| |
| |
| @Target(ElementType.FIELD) |
| @Retention(RetentionPolicy.RUNTIME) |
| public @interface MyFiled { |
| |
| String decipher(); |
| |
| int length(); |
| } |
| |
| package com.example.demo.annotation; |
| |
| import org.junit.jupiter.api.Test; |
| |
| import java.lang.reflect.Field; |
| |
| |
| |
| |
| |
| public class MyFiledTest { |
| |
| @MyFiled(decipher = "用户名", length = 12) |
| private String userName; |
| |
| @MyFiled(decipher = "用户名", length = 12) |
| private String user; |
| |
| @Test |
| public void test() { |
| |
| Class<MyFiledTest> myFiledTestClass = MyFiledTest.class; |
| Field[] declaredFields = myFiledTestClass.getDeclaredFields(); |
| for (Field declaredField : declaredFields) { |
| |
| if (declaredField.isAnnotationPresent(MyFiled.class)) { |
| MyFiled annotation = declaredField.getAnnotation(MyFiled.class); |
| System.out.println("字段: " + declaredField.getName() + " 姓名: " + annotation.decipher() + " 长度: " |
| + annotation.length()); |
| |
| |
| } |
| } |
| } |
| } |
| |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?