1.前言
在springmvc及springboot中,注解随处可见,我们几乎每天都在跟他打交道;那么如何自定义注解呢?自定义注解会不会更香呢
2.Java注解理解
Java 注解(Annotation)又称 Java 标注,是 JDK5.0 引入的一种注释机制。Java 语言中的类、方法、变量、参数和包等都可以被标注。和 Javadoc 不同,Java 标注可以通过反射获取标注内容。在编译器生成类文件时,标注可以被嵌入到字节码中。Java 虚拟机可以保留标注内容,在运行时可以获取到标注内容 。 当然它也支持自定义 Java 标注。
3.如何自定义注解
3.1注解的分类
1.内置注解,例如@Override
2.元注解,注解其他注解的基础注解
3.自定义注解
3.2 元注解理解
一般地,常用的元注解主要有以下四个:
1.@Target
2.@Retention
3.@Documented
4.@Inhrited
@Target
修饰注解的使用范围:packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量(如循环变量、catch参数)
ElementType取值:
1.CONSTRUCTOR:用于描述构造器
2.FIELD:用于描述域
3.LOCAL_VARIABLE:用于描述局部变量
4.METHOD:用于描述方法
5.PACKAGE:用于描述包
6.PARAMETER:用于描述参数
7.TYPE:用于描述类、接口(包括注解类型) 或enum声明
@Retention
修饰注解被保留的时间长短:某些Annotation仅出现在源代码中,而被编译器丢弃;而另一些却被编译在class文件中;编译在class文件中的Annotation可能会被虚拟机忽略,而另一些在class被装载时将被读取(请注意并不影响class的执行,因为Annotation与class在使用上是被分离的)。使用这个meta-Annotation可以对 Annotation的“生命周期”限制。
RetentionPoicy取值
1.SOURCE:在源文件中有效(即源文件保留)
2.CLASS:在class文件中有效(即class保留)
3.RUNTIME:在运行时有效(即运行时保留)
@Document
用于描述其它类型的注解应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。Documented是一个标记注解,没有成员。主要表示需要在什么级别保存该注释信息
@Inhrited
@Inherited阐述了某个被标注的类型是被继承的。如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。
@Inherited annotation类型是被标注过的class的子类所继承。类并不从它所实现的接口继承annotation,方法并不从它所重载的方法继承annotation。
当@Inherited annotation类型标注的annotation的Retention是RetentionPolicy.RUNTIME,则反射API增强了这种继承性。如果我们使用java.lang.reflect去查询一个@Inherited annotation类型的annotation时,反射代码检查将展开工作:检查class和其父类,直到发现指定的annotation类型被发现,或者到达类继承结构的顶层。
3.3 如何自定义注解
1.自定义权限注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Authority{
String value() default "";
}
2.controler或service添加自定义注解
@GetMapping("/user/info")
@Authority("user")
public Map<String, Object> getUserInfo() {
...
}
3.实现filter,通过反射获取自定义注解的值
@Component
public class MyInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
Authority authority= method.getAnnotation(Authority.class);
String value = authority.getValue();
//获取到value进行相关的逻辑判断
if (xxx(value)) {
//拦截
return false;
}
}
return true;
}
}
4.注册filter
@EnableWebMvc
@Configuration
public class MyInterceptorConfigurer implements WebMvcConfigurer {
@Autowired
private MyInterceptor myInterceptor ;
@Override
public void addInterceptors(InterceptorRegistry registry) {
// 注册拦截器
InterceptorRegistration ir = registry.addInterceptor(myInterceptor );
// 配置拦截的路径
ir.addPathPatterns("/**");
// 配置不拦截的路径
ir.excludePathPatterns("/static/**");
// 配置不拦截的路径
ir.excludePathPatterns("/**.html");
// exclude ico
ir.excludePathPatterns("/**.ico");
ir.excludePathPatterns("/webjars/**");
}
}
好了,自定义注解实现的前置拦截就实现呢!