自定义注解是Java语言提供的一种元编程(metaprogramming)机制,它允许开发者在代码中添加自己的元数据(metadata),以便在程序运行时进行解析和处理。 通过注解我们可以免去繁琐的配置过程,简化开发流程,可以解决很多实际开发过程中的痛点、难点,让我们可以提出更多更合理的非侵入式解决方案。 以下是一些使用自定义注解的原因和好处:
提供额外的元数据:自定义注解可以通过在源代码中添加额外的元数据,用于描述类、方法、字段等程序元素的特性和属性。这些元数据可以被程序在运行时获取,以改变程序的行为或提供其他功能。
简化代码和提高可读性:通过自定义注解,可以将一些复杂的逻辑或配置信息从代码中抽离出来,以注解的形式进行声明和使用。这样可以减少代码的重复性,使代码更加简洁和易读。
可以通过注解处理器实现代码自动化:Java提供了注解处理器(Annotation Processor)的API,可以用于在编译时处理注解。通过编写自定义的注解处理器,可以根据注解生成额外的代码或进行其他代码转换和生成操作,实现代码自动生成、自动化配置等功能。
支持框架和库的扩展性:很多开源框架和库都提供了一些特定的自定义注解,用于扩展和定制它们的行为。通过使用框架或库提供的自定义注解,可以更灵活地利用其功能和特性,以满足具体的需求。
实现代码级别的验证和约束:自定义注解可以用于实现一些代码级别的验证和约束。通过在目标元素上添加注解,可以为该元素定义一些验证规则,如参数非空检查、权限校验等。在编译器或运行时,可以根据注解对代码进行静态或动态的验证,以提高代码的健壮性和安全性。
总的来说,自定义注解是一种扩展Java语言的机制, 能够为程序添加额外的元数据、简化代码、实现自动化和增强可读性等优势。它在许多框架、库和工具中得到了广泛的应用,以提供更灵活和强大的功能。
自定义注解的工作原理大致如下:
import java.lang.annotation.*;
@Documented
@Target({ElementType.TYPE,ElementType.METHOD,ElementType.FIELD})
@Inherited
@Retention(RetentionPolicy.RUNTIME)
public @interface NameAnnotation {
String name() default "未识别的名称";
}
import tracy.annotation.NameAnnotation;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
@NameAnnotation(name = "学生类")
@Data
@AllArgsConstructor
public class Student {
@NameAnnotation(name = "姓名属性")
private String name;
@NameAnnotation(name = "年龄属性")
private Integer age;
@NameAnnotation(name = "性别属性")
private String gender;
@NameAnnotation(name = "打印方法")
public void print(boolean detailed){
if(detailed){
System.out.println(this.toString());
}else{
System.out.println("学生"+this.name);
}
}
public static void main(String[] args) {
//创建了一个Student对象并打印相关信息
Student student=new Student("tracy",18,"female");
student.print(true);
//打印该对象所属类的相关信息
System.out.println("类信息:");
System.out.println((student.getClass().getAnnotation(NameAnnotation.class)).name());
System.out.println("方法信息:");
for(Method method:student.getClass().getDeclaredMethods()){
for (Annotation a:method.getAnnotations()){
System.out.println(((NameAnnotation)a).name());
}
}
System.out.println("属性信息:");
for(Field field:student.getClass().getDeclaredFields()){
for (Annotation a:field.getAnnotations()){
System.out.println(((NameAnnotation)a).name());
}
}
}
}
在 Spring Boot 中,可以使用一些自定义注解的元注解来定义和扩展自定义注解。以下是一些常见的元注解:
@Retention:该元注解用于指定注解的保留策略,决定注解的生命周期。常见的参数有:
@Target:该元注解用于指定注解可以应用的目标元素类型,如类、方法、字段等。常见的参数有:
@Inherited:该元注解用于指定注解是否可以被继承。如果一个类使用了被 @Inherited 注解修饰的注解,则其子类也会继承该注解。
@Documented:该元注解用于指定注解是否应该被 javadoc 文档化。没有 @Documented 元注解修饰的注解在生成 javadoc 文档时不会显示在文档中。
@Repeatable:该元注解用于指定注解是否可重复应用于同一元素上。需要在自定义的重复注解上添加 @Repeatable 注解,并指定一个容器注解来存放重复的注解。
Spring Boot 拦截器是一种在 Spring Boot 应用程序中拦截请求并进行特定处理的技术,可以用于记录日志、做权限校验、性能监控等。在 Spring Boot 中,拦截器主要是通过实现 HandlerInterceptor
接口来实现的。
Spring Boot 拦截器的使用方法与 Spring MVC 中的拦截器类似。可以通过实现 HandlerInterceptor
接口,并在配置类中进行注册。以下是一个简单的示例代码:
以下是一个示例代码,展示了如何在 Spring Boot 中使用拦截器对请求进行拦截并进行特定处理:
首先,我们需要创建一个 MyInterceptor
类,实现 HandlerInterceptor
接口,并重写其中的方法:
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
@Component
public class MyInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// 在请求处理之前进行操作
System.out.println("Interceptor: preHandle method is called");
return true; // 返回 true 表示继续执行后续操作,返回 false 则表示拦截请求
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
// 在请求处理之后进行操作
System.out.println("Interceptor: postHandle method is called");
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception ex) throws Exception {
// 在请求完成之后进行操作
System.out.println("Interceptor: afterCompletion method is called");
}
}
在上述代码中,我们定义了一个 MyInterceptor
类,并实现了 HandlerInterceptor
接口。在 preHandle()
方法中,我们可以添加对请求的拦截逻辑,在 postHandle()
和 afterCompletion()
方法中,我们可以添加对请求处理之后的操作,例如记录日志等。
接下来,我们需要在配置类中注册拦截器:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MyConfig implements WebMvcConfigurer {
@Autowired
private MyInterceptor myInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 注册拦截器,指定拦截路径
registry.addInterceptor(myInterceptor).addPathPatterns("/api/**");
}
}
在上述代码中,我们创建了一个 MyConfig
配置类,并实现了 WebMvcConfigurer
接口。在该类中,我们通过 @Autowired
注解注入了 MyInterceptor
类,并在 addInterceptors()
方法中对拦截器进行了配置。在上述代码中,我们指定了拦截 /api
路径下的所有请求。
最后,我们可以在控制器中添加一个请求处理方法,用来测试拦截器的效果:
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MyController {
@GetMapping("/api/test")
public String test() {
return "Hello, World!";
}
}
在上述代码中,我们创建了一个 MyController
控制器类,并添加了一个处理 /api/test
请求的方法。
当我们运行应用程序并访问 /api/test
路径时,MyInterceptor
中的拦截逻辑就会被执行,并输出日志信息。
需要注意的是,拦截器的执行顺序可以通过 order
属性进行配置,默认情况下,拦截器的执行顺序与注册顺序相同。另外,拦截器也可以用于对请求进行权限校验、日志记录、性能监控等操作。
需要注意的是,Spring Boot 中的拦截器与过滤器(Filter)和切面(Aspect)等技术一起使用可以实现更加强大的功能。在使用拦截器时,应该遵循开放封闭原则,尽可能避免修改原有代码。同时,拦截器的使用也应该尽量保证代码的可读性和可维护性。
https://blog.csdn.net/qq_54936371/article/details/122576023
https://zhuanlan.zhihu.com/p/468882010