zoukankan      html  css  js  c++  java
  • JAVA基础5--注解的实现原理

    一、注解简介

    注解也叫元数据,是JDK1.5版本开始引入的一个特性,用于对代码进行标记说明,可以对包、类、接口、字段、方法参数、局部变量等进行注解修饰

    1.1、注解的类型

    1、JDK注解和框架注解:JDK本身提供了很多注解比如@Resource、@PostConstruct等;另外常用的框架也提供了很多注解,比如Spring的@Autowired,@Service等等,这些注解使用时会自动被JDK或框架进行识别解析;

    2、元注解:元注解用于修饰注解的,如@Retention(标明注解被保留的阶段)、@Target(标明注解使用的范围)、@Inherited(标明注解可继承)、@Documented(标明是否生成javadoc文档)

    3、自定义注解:用户可以根据自行需求自定义注解

    1.2、元注解

    @Retention:定义注解的生命周期,默认是CLASS,取值范围如下:

    SOURCE 在编译阶段被抛弃,通常用于编译时使用,比如@Override注解
    CLASS 在编译阶段会被写入字节码,当类加载的时候会被丢弃
    RUNTIME 不会被丢弃,运行期间也可以使用,所以通过反射机制就可以读取该注解的信息,通常自定义注解都会采用RUNTIME类型

    @Target:定义注解可以修饰的目标,默认是可以修饰任意目标,取值范围如下

    TYPE 用于描述类、接口或enum声明,如@Service、@Component等
    FIELD 用于描述属性,比如@JSONField等
    METHOD 用于描述方法,比如@Override
    PARAMETER 用于描述方法参数,比如Mybatis框架中的@Param
    CONSTRUCTOR 用于描述构造函数
    LOCAL_VARIABLE 用于描述局部变量
    ANNOTATION_TYPE 用于描述注解类型,比如@Target本身,@Retention,@Document注解等
    PACKAGE 用于描述包名
    TYPE_PARAMETER 用于描述参数类型
    TYPE_USE 表示该注解能使用在使用类型的任意语句中

    @Inherited:定义注解是否继承给子类

    当@Inherited注解修饰了一个注解,那么如果这个注解修饰了一个类,那么这个类的子类也会继承该注解

    @Documented:定义注解是否将注解信息加到Java文档中

    1.3、注解的组成

    注解通常有几个部分组成,包括修饰该注解的元注解,注解名称和注解方法,当然也可以将注解仅当作标记作用,没有任何方法也行,比如@Override注解就没有任何方法,仅当作标记使用

    二、注解的使用

    通常我们Web服务提供接口需要用户登录之后才可以访问,此时如果每个接口都判断下用户是否登录就会冗余很多的代码,所以需要在执行接口方法之前有一层验证用户登录的逻辑,可以通过过滤器,拦截器等方式实现,此时就可以配合注解来实现,在需要进行登录验证的方法上添加一个自定义的注解,然后每个添加了注解的方法就需要验证登录,没有注解的方法就不需要登录,实现方式如下:

    自定义注解@Logined

    @Documented
    @Target(ElementType.METHOD) /** 修饰方法*/
    @Retention(RetentionPolicy.RUNTIME)/** 生命周期为运行期间*/
    public @interface Logined {
    
        /** 定义方法,如果没有登录的情况下是否直接抛异常*/
        boolean exception() default false;
    }

    定义了注解之后就可以直接使用,但是想要使注解的效果生效,就需要有一套获取注解并处理业务的逻辑,此时就离不开Java的反射机制,需要通过反射机制获取到修饰在方法、类、属性上的注解来进行判断是否加了注解。

    另外在使用Spring框架时,可以配置AOP来配合使用自定义注解,比如以下案例就是用来处理@Logined注解的逻辑:

    @Aspect
    @Component
    public class LoginAspect {
    
        @Around("@annotation(com.test.annotation.Logined)")
        public Object doBefore(ProceedingJoinPoint jp) throws Throwable {
            if (MessageConfig.LOCAL.get() == null) {
                System.out.println("请求用户为空,返回401:" + jp.getSignature().getName());
                return Result.returnUnauthorized();
            }
            return jp.proceed();
        }
    }

    三、注解的实现原理

    注解本身没有任何逻辑,只能起到标记的作用,实现的逻辑完全取决于处理注解的逻辑,而处理注解就需要先找到注解,此时就离不开Java的反射机制,主要是通过Constructor、Class、Method、Field等反射相关类的getAnnotation(Class annotationClass)方法获取对应的注解,如果能获取到注解那么就表示被注解修饰了,案例如下:

     1 /** 1.查找类上的注解 */
     2         Annotation classAnnotation = cla.getAnnotation(Logined.class);
     3         if(classAnnotation != null){
     4             System.out.println("类被@Logined注解修饰");
     5         }
     6 
     7         /** 2.查找方法上的注解 */
     8         Method[] methods = cla.getMethods();
     9         for (Method method : methods){
    10             if(method.getAnnotation(Logined.class) != null){
    11                 System.out.println("方法:" + method.getName() + "被注解@Logined" + "修饰");
    12             }
    13         }
    14 
    15         /** 3.查找属性上的注解 */
    16         Field[] fields = cla.getFields();
    17         for (Field field : fields){
    18             if(field.getAnnotation(Logined.class) != null){
    19                 System.out.println("属性:" + field + "被注解@Logined" + "修饰");
    20             }
    21         }
    22 
    23         /** 4.查找构造函数上的注解 */
    24         Constructor constructor = cla.getConstructor(String.class);
    25         if(constructor.getAnnotation(Logined.class)!=null){
    26             System.out.println("构造器被@Logined注解修饰");
    27         }
  • 相关阅读:
    流处理 —— Spark Streaming中的Window操作
    Spring框架参考手册(4.2.6版本)翻译——第三部分 核心技术 6.10.8 提供带注解的限定符元数据
    Spring框架参考手册(4.2.6版本)翻译——第三部分 核心技术 6.10.7 为自动检测组件提供作用域
    Spring框架参考手册(4.2.6版本)翻译——第三部分 核心技术 6.10.6 给自动检测组件命名
    Spring框架参考手册(4.2.6版本)翻译——第三部分 核心技术 6.10.5 在组件中定义bean的元数据
    Spring框架参考手册(4.2.6版本)翻译——第三部分 核心技术 6.10.4 使用过滤器自定义扫描
    Spring框架参考手册(4.2.6版本)翻译——第三部分 核心技术 6.10.3 自动检测类和注册bean的定义
    Spring框架参考手册(4.2.6版本)翻译——第三部分 核心技术 6.10.2 元注解
    Spring框架参考手册(4.2.6版本)翻译——第三部分 核心技术 6.10.1 @Component和深层的构造型注解
    Spring框架参考手册(4.2.6版本)翻译——第三部分 核心技术 6.10 类路径扫描和被管理的组件
  • 原文地址:https://www.cnblogs.com/jackion5/p/14700195.html
Copyright © 2011-2022 走看看