5分钟搞懂java注解@Annotation的具体使用

 更新时间:2019年05月15日 09:34:38   作者:打怪升级路  
这篇文章主要介绍了5分钟搞懂java注解@Annotation的具体使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

首先一句话结论:注解就是一种通过在类、方法、或者属性等上使用类似@xxx的方式进行“打标签”,然后可以通过反射机制对标签的内容进行解析并进行相应处理的手段。

注解是java中的一个重要知识点,从java5后开始引入,尤其在spring框架中大量使用。比较常用的有@controller、@service等等各种,本文将从注解的实现原理出发,通过一些demo代码的实现,进行分析。

一、 注解定义方式

直接上代码,看看spring中@Service注解的定义就知道了:

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Service {

 String value() default "";
 
}

可以看到注解的定义和接口定义很像,但是多了@字符,注解的定义上有以下约定:

  • 只能定义属性名,不能定义方法
  • 属性的可见性只有public和default,不写则默认后者
  • 属性的类型只能支持:基本数据类型、string、class、enum、Annotation类型及以上类型的数组
  • 可以加上defult关键字指明默认值,当某字段不指明默认值时,必须在进行注解标注的时候进行此字段值的指定。
  • 当使用value作为属性名称时,可以不显式指定value=“xxx”,如可以直接使用@Service("xxxService")

二、元注解

所谓元注解就是java中默认实现的专门对注解进行注解的注解。元注解的总数就5个,下面我们以上面讲到的@Service注解为例子各个击破:

1.@Target

此注解用于表示当前注解的使用范围,@Target({ElementType.TYPE})就代表着@Service这个注解是专门用来注解到类、接口、或者枚举类型上面的,当在方法上面加这个注解时,就会报错。可以看到注解位置是一个枚举类型,完整定义如下

public enum ElementType {
  /** Class, interface (including annotation type), or enum declaration */
  TYPE,

  /** Field declaration (includes enum constants) */
  FIELD,

  /** Method declaration */
  METHOD,

  /** Formal parameter declaration */
  PARAMETER,

  /** Constructor declaration */
  CONSTRUCTOR,

  /** Local variable declaration */
  LOCAL_VARIABLE,

  /** Annotation type declaration */
  ANNOTATION_TYPE,

  /** Package declaration */
  PACKAGE,

  /**
   * Type parameter declaration
   *
   * @since 1.8
   */
  TYPE_PARAMETER,

  /**
   * Use of a type
   *
   * @since 1.8
   */
  TYPE_USE
}

2.@Retention

此注解用于表示当前注解的生命周期,说人话就是这个注解作用会保留到什么时候,如@Retention(RetentionPolicy.RUNTIME)就表示在程序运行期间依然有效,此时就可以通过反射拿到注解的信息,完整的枚举定义如下

public enum RetentionPolicy {
  /**
   * Annotations are to be discarded by the compiler.
   */
  SOURCE,

  /**
   * Annotations are to be recorded in the class file by the compiler
   * but need not be retained by the VM at run time. This is the default
   * behavior.
   */
  CLASS,

  /**
   * Annotations are to be recorded in the class file by the compiler and
   * retained by the VM at run time, so they may be read reflectively.
   *
   * @see java.lang.reflect.AnnotatedElement
   */
  RUNTIME
}

3.@Documented

当被此注解所注解时,使用javadoc工具生成文档就会带有注解信息。

4.@Inherited

此注解与继承有关,当A注解添加此注解后,将A注解添加到某类上,此类的子类就会继承A注解。

@Inherited
public @interface A{
}

@A
public class Parent{}

public class Son entends Parant{}//Son类继承了父类的A注解

5.@Repeatable

此注解顾名思义是拥有可以重复注解的能力。想象这样一个场景,我们需要定时执行某个任务,需要在每周一和周三执行,并且这个时间是可以灵活调整的,此时这个元注解就能派上用场:

@Repeatable(Schedules.class)
public @interface Schedule {
  String date();
}

public @interface Schedules {
  Schedule[] value();
}

@Schedule(date = "周一")
@Schedule(date = "周三")
public class Executor {
}

注意看到此元注解后面括号里内容,在这指定的类叫做容器注解,意思是保存这多个注解的容器,故我们创建一个@Schedules注解作为@Schedule的容器注解,容器注解必须含有一个名字为value,返回类型为需放入此容器的注解数组的属性。

三、自定义实现一个注解

下面我们以web项目中非常常见的鉴权场景为例自己实现一个自定义注解。

首先我们定义系统的使用人员身份,有超级管理员、管理员、访客三种身份。

public enum IdentityEnums {

  SUPER_ADMIN,
  ADMIN,
  VISIVOR

}

接下来我们定义一个权限注解:

@Target({ElementType.TYPE,ElementType.METHOD})
@Documented
@Retention(RetentionPolicy.RUNTIME)
public @interface Authorization {

  IdentityEnums[] value();
  
}


然后使用拦截器的方式,对所有页面进行统一的鉴权管理,此处只展示一些关键代码:

public class AuthInterceptor implements HandlerInterceptor {

  @Override
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {

    if (handler instanceof HandlerMethod)
    {
      IdentityEnums user = getIdentityFromRequset(request);//这里从request里获取账号信息并判断身份,自己实现
      Authorization auth =((HandlerMethod) handler).getMethodAnnotation(Authorization.class);//获取方法上面的注解
      if (!Arrays.asList(auth.value()).contains(user)){
        return false;
      }
    }
    return true;
  }
}

最后在spring配置文件中对拦截器进行配置开启拦截器:

<!-- 拦截器 -->
 <mvc:interceptors>
 <mvc:interceptor>
  <!-- 匹配的是url路径, 如果不配置或/**,将拦截所有的Controller -->
  <mvc:mapping path="/**" />
  <!-- 拦截器类 -->
  <bean
  class="com.xx.xx.AuthInterceptor"></bean>
 </mvc:interceptor>
 </mvc:interceptors>

在实际使用中,我们将在方法上面添加此自定义注解,当身份权限符合时,才能对页面进行访问,使用方式如下:
@ResponseBody

@RequestMapping(value = "/management")
@Authorization({IdentityEnums.ADMIN,IdentityEnums.SUPER_ADMIN})
public String management(HttpServletRequest request, HttpServletResponse response)
{
  log.info("has permission!");
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • springmvc html资源请求404的问题解决并分析

    springmvc html资源请求404的问题解决并分析

    这篇文章主要介绍了springmvc html资源请求404的问题解决并分析,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-09-09
  • Java基础知识精通二维数组的应用

    Java基础知识精通二维数组的应用

    为了方便组织各种信息,计算机常将信息以表的形式进行组织,然后再以行和列的形式呈现出来。二维数组的结构决定了其能非常方便地表示计算机中的表,以第一个下标表示元素所在的行,第二个下标表示元素所在的列。下面简单了解一下二维数组,包括数组的声明和初始化
    2022-04-04
  • springboot对接minio的webhook完整步骤记录

    springboot对接minio的webhook完整步骤记录

    Minio是一款开源的对象存储服务,它致力于为开发者提供简单、高性能、高可用的云存储解决方案,下面这篇文章主要给大家介绍了关于springboot对接minio的webhook的相关资料,需要的朋友可以参考下
    2024-07-07
  • 解决slf4j 和 logback-classic遇到的坑

    解决slf4j 和 logback-classic遇到的坑

    这篇文章主要介绍了解决slf4j 和 logback-classic遇到的坑,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • 浅谈BeanPostProcessor加载次序及其对Bean造成的影响分析

    浅谈BeanPostProcessor加载次序及其对Bean造成的影响分析

    这篇文章主要介绍了浅谈BeanPostProcessor加载次序及其对Bean造成的影响分析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-04-04
  • SpringBoot2 整合 ClickHouse数据库案例解析

    SpringBoot2 整合 ClickHouse数据库案例解析

    这篇文章主要介绍了SpringBoot2 整合 ClickHouse数据库案例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-10-10
  • 浅谈Java中的private方法是否可以被代理

    浅谈Java中的private方法是否可以被代理

    这篇文章主要介绍了浅谈Java中的private方法是否可以被代理,在 Java 8之前,接口可以有常量变量和抽象方法,我们不能在接口中提供方法实现,如果我们要提供抽象方法和非抽象方法(方法与实现)的组合,那么我们就得使用抽象类,需要的朋友可以参考下
    2023-12-12
  • 在Java和PostgreSQL枚举之间转换的通用方法

    在Java和PostgreSQL枚举之间转换的通用方法

    枚举类型(enum)是一种方便的数据类型,允许我们指定一个常量列表,对象字段或数据库列可以设置为该列表中的值,在本文中,我将回顾处理Java和PostgreSQL枚举转换的通用方法,需要的朋友可以参考下
    2023-10-10
  • java编程ThreadLocal上下传递源码解析

    java编程ThreadLocal上下传递源码解析

    这篇文章主要为大家介绍了java编程中ThreadLocal提供的上下传递方式的源码解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步
    2022-03-03
  • Spring通过ApplicationContext主动获取bean的方法讲解

    Spring通过ApplicationContext主动获取bean的方法讲解

    今天小编就为大家分享一篇关于Spring通过ApplicationContext主动获取bean的方法讲解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-03-03

最新评论