深入浅出java注解

参考资料

参考链接1

如何定义一个注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface MyAnnotation {

    String title() default "";

    String[] urls() default "";

    boolean isTrue() default true;
}

获取注解

反射

在这里插入图片描述

前提条件

只有 RetentionPolicy.RUNTIME 的注解可以被反射获取。

@Target(ElementType.TYPE)
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@interface Ann1 {
}

@Ann1
public class Ann1Client {
    public static void main(String[] args) {
        Annotation[] annotations = Ann1Client.class.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
        }
    }
}
ElementType.TYPE_PARAMETER
@Target(value = {
        ElementType.TYPE_PARAMETER
})
@Retention(RetentionPolicy.RUNTIME)
@interface Ann7 {
    String value();
}

@Target(value = {
        ElementType.TYPE_USE
})
@Retention(RetentionPolicy.RUNTIME)
public @interface Ann8 {
    String value();
}

public class UseAnn100<@Ann7("this is A") @Ann8("this is AA") A,
        @Ann7("this is B") @Ann8("this is BB") B,
        @Ann7("this is C") @Ann8("this is CC") C> {
    public static void main(String[] args) {
        TypeVariable<Class<UseAnn100>>[] typeParameters = UseAnn100.class.getTypeParameters();
        for (TypeVariable<Class<UseAnn100>> typeParameter : typeParameters) {
            Annotation[] annotations = typeParameter.getAnnotations();
            for (Annotation annotation : annotations) {
                System.out.println(annotation);
            }
        }
    }
}
ElementType.PACKAGE

在这里插入图片描述

@Target(value = {
        ElementType.PACKAGE
})
@Retention(RetentionPolicy.RUNTIME)
public @interface Ann9 {

    String value();
}

@Ann9("this is type package")
package com.example.lurenjia.spring.c16;

public class PackageInfoMain {
    public static void main(String[] args) {
        Package p = Package.getPackage("com.example.lurenjia.spring.c16");
        Annotation[] annotations = p.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
        }
    }
}
ElementType.METHOD
@Target(value = {
        ElementType.METHOD
})
@Retention(RetentionPolicy.RUNTIME)
public @interface Ann101 {
    String value();
}

public class UseAnn101 {

    @Ann101("a")
    public void a() {

    }

    public static void main(String[] args) {
        Method[] declaredMethods = UseAnn101.class.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            Annotation[] annotations = declaredMethod.getAnnotations();
            for (Annotation annotation : annotations) {
                System.out.println(annotation);
            }
        }
    }
}
ElementType.CONSTRUCTOR
@Target(value = {
        ElementType.CONSTRUCTOR
})
@Retention(RetentionPolicy.RUNTIME)
public @interface Ann102 {
    String value();
}

public class UseAnn102 {

    @Ann102(value = "const")
    public UseAnn102() {
    }

    public static void main(String[] args) {
        Constructor<?>[] declaredConstructors = UseAnn102.class.getDeclaredConstructors();
        for (Constructor<?> declaredConstructor : declaredConstructors) {
            Annotation[] declaredAnnotations = declaredConstructor.getDeclaredAnnotations();
            for (Annotation declaredAnnotation : declaredAnnotations) {
                System.out.println(declaredAnnotation);
            }
        }
    }
}
ElementType.PARAMETER
@Target(value = {
        ElementType.PARAMETER
})
@Retention(RetentionPolicy.RUNTIME)
public @interface Ann103 {
    String value();
}

public class UseAnn103 {
    public void a(@Ann103("a") int a, @Ann103("b") int b) {
    }
    public static void main(String[] args) {
        Method[] declaredMethods = UseAnn103.class.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            Parameter[] parameters = declaredMethod.getParameters();
            for (Parameter parameter : parameters) {
                Annotation[] annotations = parameter.getAnnotations();
                for (Annotation annotation : annotations) {
                    System.out.println(annotation);
                }
            }
        }
    }
}
ElementType.FIELD
@Target(value = {
        ElementType.FIELD
})
@Retention(RetentionPolicy.RUNTIME)
public @interface Ann104 {
    String value();
}

public class UseAnn104 {

    @Ann104("a . ")
    int a;
    @Ann104("b . ")
    int b;

    public static void main(String[] args) {
        Field[] fields = UseAnn104.class.getDeclaredFields();
        for (Field field : fields) {
            Annotation[] annotations = field.getAnnotations();
            for (Annotation annotation : annotations) {
                System.out.println(annotation);
            }
        }
    }
}
ElementType.LOCAL_VARIABLE
@Target(value = {
        ElementType.LOCAL_VARIABLE
})
@Retention(RetentionPolicy.RUNTIME)
public @interface Ann105 {
    String value();
}
public class UseAnn105 {
    public UseAnn105() {
    }

    public void a(int a, int b) {
    }     
}

由于在 jdk8的class文件也就是字节码中不保留局部变量上的注解信息,所以 ElementType.LOCAL_VARIABLE 暂时没有实际效果。

ElementType.ANNOTATION_TYPE
@Target(value = {
        ElementType.ANNOTATION_TYPE
})
@Retention(RetentionPolicy.RUNTIME)
public @interface Ann106 {
    String value();
}

@Target(value = {
        ElementType.FIELD
})
@Ann106("Ann106")
@Retention(RetentionPolicy.RUNTIME)
public @interface Ann104 {
    String value();
}

public class UseAnn106 {

    public static void main(String[] args) {
        Annotation[] annotations = Ann105.class.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
        }
    }
}

ElementType.TYPE_USE

可以当任何类型来使用

@Target({ElementType.TYPE_USE})
@Retention(RetentionPolicy.RUNTIME)
@interface Ann10 {
    String value();
}

Aop

@Aspect
@Component
public class MyAnnotationAop {

    private final static Logger logger = LoggerFactory.getLogger(MyAnnotationAop.class);

    @Pointcut("@annotation(com.example.micannotation.annotation.MyAnnotation)")
    public void MyAnnotationPointcut() {

    }

    /**
     * 方式一
     * @param joinPoint
     */
    @Before("MyAnnotationPointcut()")
    public void before(JoinPoint joinPoint) {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        MyAnnotation annotation = method.getAnnotation(MyAnnotation.class);
        String title = annotation.title();
        logger.info(" 1 title = {}", title);
        Object[] args = joinPoint.getArgs();
        logger.info(Arrays.toString(args));
    }

    /**
     * 方式二
     * @param joinPoint
     * @param annotation
     */
    @Before("@annotation(annotation)")
    public void before(JoinPoint joinPoint, MyAnnotation annotation) {
        String title = annotation.title();
        logger.info(" 2 title = {}", title);
        Object[] args = joinPoint.getArgs();
        logger.info(Arrays.toString(args));
    }
}

常见的注解

内置注解

@SuppressWarnings 消除警告

@Override 重写方法

@Deprecated 过时方法,不推荐使用

元注解

修饰注解的注解

指定注解的使用范围:@Target

 ElementType[] value();
 
public enum ElementType {
       /*类、接口、枚举、注解上面*/
    TYPE,
    /*字段上*/
    FIELD,
    /*方法上*/
    METHOD,
    /*方法的参数上*/
    PARAMETER,
    /*构造函数上*/
    CONSTRUCTOR,
    /*本地变量上*/
    LOCAL_VARIABLE,
    /*注解上*/
    ANNOTATION_TYPE,
    /*包上*/
    PACKAGE,
    /*类型参数上*/
    TYPE_PARAMETER,
    /*类型名称上*/
    TYPE_USE
}

注解的作用对象

指定注解的保留策略:@Retention

public @interface Retention {
    RetentionPolicy value();
}

public enum RetentionPolicy {
  	编译后丢弃,也就是java文件生效
    SOURCE,
    class文件生效,jvm运行时丢失   
    CLASS,
    jvm运行时仍然存在
    RUNTIME
}

@Documented

@Inherit:实现类之间的注解继承

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface Ann21 {
}

@Ann21
public class UseAnn21 {
}

@Ann21
public interface UseAnn21_ {
}

public class UseAnn21Son extends UseAnn21 {
    public static void main(String[] args) {
        Annotation[] annotations = UseAnn21Son.class.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
        }
    }
}

public class UseAnn21Son_ implements UseAnn21_{
    public static void main(String[] args) {
        Annotation[] annotations = UseAnn21Son_.class.getAnnotations();
        for (Annotation annotation : annotations) {
            System.out.println(annotation);
        }
    }
}

@com.example.lurenjia.spring.c16.Ann21()

注意,接口的实现类不会继承接口上被 @Inherit 修饰的注解

@Repeatable重复使用注解

如果我们尝试重复使用一个注解,默认下会提示如下的错误。
在这里插入图片描述

不使用 @Repeatable 怎么实现 ?

@MyAnnotations(array = {@MyAnnotation(title = "is title"), @MyAnnotation(title = "is title2")})
---
@Retention(RetentionPolicy.RUNTIME)
@Target(value = {ElementType.TYPE, ElementType.METHOD})
@Documented
public @interface MyAnnotations {
    MyAnnotation[] array();
}

使用 @Repeatable
需要定义两个注解,一个容器注解和一个原始注解。

@Target(value = {
        ElementType.TYPE_USE
})
@Retention(RetentionPolicy.RUNTIME)
@Repeatable(Ann110s.class)
public @interface Ann110 {
    
}
@Target(value = {
        ElementType.TYPE_USE
})
@Retention(RetentionPolicy.RUNTIME)
public @interface Ann110s {

    Ann110[] value();
}

使用 @Repeatable 后多了一种使用方法

@Ann110("1")
@Ann110("2")
@Ann110("3")
@Ann110("4")
public class UseAnn110s {
    public static void main(String[] args) {

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值