Java——注解(Annotation)

桃扇骨 2021-06-10 20:41 741阅读 0赞

1. 简介

官方解释:Java 注解用于为 Java 代码提供元数据。作为元数据,注解不直接影响你的代码执行,但也有一些类型的注解实际上可以用于这一目的。

注解的定义:
通俗的来讲,注解就如同标签。一个注解准确意义上来说,只不过是一种特殊的注释而已,如果没有解析它的代码,它可能连注释都不如。

注解的本质就是一个继承了 Annotation 接口的接口,下面是注解 @Override 的定义,其实它本质上就是:

  1. public interface Override extends Annotation{
  2. }

解析一个类或者方法的注解一般有两种方式:

  • 编译期直接的扫描
  • 运行期反射

如上面所说的注解@Override,一旦编译器检测到某个方法被修饰了 @Override 注解,编译器就会检查当前方法的方法签名是否真正重写了父类的某个方法,也就是比较父类中是否具有一个同样的方法签名。

Java中内置的几个注解:
在这里插入图片描述
常见的作用:

  • 生成说明文档,@see @param @return 等
  • 编译时检查格式,比如说@Override,放在方法前,编译时会检查格式
  • 替代文件的配置功能,比如Spring中的基于注解配置
  • 反射中,Class, Method, Field 等函数有许多注解相关接口,通过反射拿到Class, Method, Field类,就能够通过getAnnotation(Class)拿到我们想要的注解并取值。

2. 创建一个注解

一般通过 @interface 关键字来定义,比如说创建一个Annotation_1注解

  1. public @interface Annotation_1 {
  2. }

如何使用它呢?

  1. @Annotation_1
  2. public class Test {
  3. }

3. 元注解

元注解可以理解为是用于修饰注解的注解,一般用在定义注解上,JAVA 中有以下几个元注解:

  • @Target:注解的作用目标(指明用于修饰方法还是修饰类),以下是常用取值
    在这里插入图片描述
  • @Retention:注解的生命周期,以下是常用取值
    在这里插入图片描述
  • @Documented:注解是否应当被包含在 JavaDoc 文档中
  • @Inherited:是否允许子类继承该注解,父类被注解,子类会继承父类的注解
  • @Repeatable:java1.8中引入,是可重复的意思,注解的值可取多个
    举个例子:

    @interface Persons {

    1. Person[] value();

    }

    //@Repeatable 注解了 Person。而 @Repeatable 后面括号中的类相当于一个容器注解。
    @Repeatable(Persons.class)
    @interface Person{

    1. String role default "";

    }
    @Person(role=”artist”)
    @Person(role=”coder”)
    @Person(role=”PM”)
    public class SuperMan{
    }

容器注解:

  1. @interface Persons {
  2. Person[] value();
  3. }

相当于这个注解里存放了好几个不一样的注解,一个类或方法只要被这个容器注解给注解了,就相当于被好几个不一样的注解给注解了

举个例子:以下就是@Override 注解的定义

  1. @Target(ElementType.METHOD)
  2. @Retention(RetentionPolicy.SOURCE)
  3. public @interface Override {
  4. }

4.反射获取注解

注解只有成员变量,不存在方法,在注解的定义中,使用无形参的形式来声明。

先定义一个注解:

  1. @Target(ElementType.FIELD)
  2. @Retention(RetentionPolicy.RUNTIME)
  3. public @interface MyField {
  4. String description();
  5. int length();
  6. }

通过反射获取注解

  1. public class MyFieldTest {
  2. //使用我们的自定义注解
  3. @MyField(description = "用户名", length = 12)
  4. private String username;
  5. @Test
  6. public void testMyField(){
  7. // 获取类模板
  8. Class c = MyFieldTest.class;
  9. // 获取所有字段
  10. for(Field f : c.getDeclaredFields()){
  11. // 判断这个字段是否有MyField注解
  12. if(f.isAnnotationPresent(MyField.class)){
  13. MyField annotation = f.getAnnotation(MyField.class);
  14. System.out.println("字段:[" + f.getName() + "], 描述:[" + annotation.description() + "], 长度:[" + annotation.length() +"]");
  15. }
  16. }
  17. }
  18. }

运行结果

  1. 字段:[username],描述:[用户名],长度[12]

5.应用:实现登录校验

使用自定义注解+拦截器来实现登录校验

使用springboot拦截器实现这样一个功能,如果方法上加了@LoginRequired,则提示用户该接口需要登录才能访问,否则不需要登录。

(1)首先定义一个LoginRequired注解

  1. @Target(ElementType.METHOD)
  2. @Retention(RetentionPolicy.RUNTIME)
  3. public @interface LoginRequired {
  4. }

(2)然后写两个简单的接口,访问sourceA,sourceB资源

  1. @RestController
  2. public class IndexController {
  3. @GetMapping("/sourceA")
  4. public String sourceA(){
  5. return "你正在访问sourceA资源";
  6. }
  7. @GetMapping("/sourceB")
  8. public String sourceB(){
  9. return "你正在访问sourceB资源";
  10. }
  11. }

(3)没添加拦截器之前成功访问
在这里插入图片描述
(4)实现spring的HandlerInterceptor 类先实现拦截器,但不拦截,只是简单打印日志,如下:

  1. public class SourceAccessInterceptor implements HandlerInterceptor {
  2. @Override
  3. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  4. System.out.println("进入拦截器了");
  5. return true;
  6. }
  7. @Override
  8. public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
  9. }
  10. @Override
  11. public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
  12. }
  13. }

(5)实现spring类WebMvcConfigurer,创建配置类把拦截器添加到拦截器链中

  1. @Configuration
  2. public class InterceptorTrainConfigurer implements WebMvcConfigurer {
  3. @Override
  4. public void addInterceptors(InterceptorRegistry registry) {
  5. registry.addInterceptor(new SourceAccessInterceptor()).addPathPatterns("/**");
  6. }
  7. }

(6)在sourceB方法上添加我们的登录注解@LoginRequired

  1. @RestController
  2. public class IndexController {
  3. @GetMapping("/sourceA")
  4. public String sourceA(){
  5. return "你正在访问sourceA资源";
  6. }
  7. @LoginRequired
  8. @GetMapping("/sourceB")
  9. public String sourceB(){
  10. return "你正在访问sourceB资源";
  11. }
  12. }

(7)简单实现登录拦截逻辑

  1. @Override
  2. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
  3. System.out.println("进入拦截器了");
  4. // 反射获取方法上的LoginRequred注解
  5. HandlerMethod handlerMethod = (HandlerMethod)handler;
  6. LoginRequired loginRequired = handlerMethod.getMethod().getAnnotation(LoginRequired.class);
  7. if(loginRequired == null){
  8. return true;
  9. }
  10. // 有LoginRequired注解说明需要登录,提示用户登录
  11. response.setContentType("application/json; charset=utf-8");
  12. response.getWriter().print("你访问的资源需要登录");
  13. return false;
  14. }

运行成功,访问sourceB时需要登录了,访问sourceA则不用登录.

发表评论

表情:
评论列表 (有 0 条评论,741人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Java-注解-Annotation

    注解作用   注解其实是代码里的特殊标记,这些标记可以在编译、类加载、运行时被读取,并执行相应的处理。通过使用 Annotation, 程序开发人员可以在不改变原有逻辑的

    相关 Java注解(Annotation)

    一、什么是注解        注解(Annotation)很重要,未来的开发模式都是基于注解的,JPA是基于注解的,Spring2.5以上都是基于注解的,Hibernat

    相关 Java Annotation 注解

    首先什么是注解? 最常见的是,在我们使用Eclipse等工具编写java代码的时候,有时候会出现一些比如@Deprecated,@Override,@SuppressWarn

    相关 java 注解Annotation

    注解相当于一种标记,在程序中加了注解就等于为程序打上了某种标记,没加,则等于没有某种标记。 以后,javac编译器,开发工具和其他程序可以用反射来了解你的类及各种元素上有无何

    相关 Java——注解Annotation

    1. 简介 官方解释:Java 注解用于为 Java 代码提供元数据。作为元数据,注解不直接影响你的代码执行,但也有一些类型的注解实际上可以用于这一目的。 注解的定义: