Java实现自定义注解(Annotation)

自定义注解入门

注解概述:
注解,可以看作是对 一个 类/方法 的一个扩展的模版,每个 类/方法 按照注解类中的规则,来为 类/方法 注解不同的参数,在用到的地方可以得到不同的 类/方法 中注解的各种参数与值。

注解规范

  • 注解参数的可支持数据类型:

  • 1.所有基本数据类型(int,float,boolean,byte,double,char,long,short)

  • 2.String类型

  • 3.Class类型

  • 4.enum类型

  • 5.Annotation类型

  • 6.以上所有类型的数组

  • Annotation类型里面的参数该怎么设定:

  • 第一,只能用public或默认(default)这两个访问权修饰.例如,String value();这里把方法设为defaul默认类型;

  • 第二,参数成员只能用基本类型byte,short,char,int,long,float,double,boolean八种基本数据类型和String,Enum,Class,annotations等数据类型,以及这一些类型的数组.例如,String value();这里的参数成员就为String;

  • 第三,如果只有一个参数成员,最好把参数名称设为"value",后加小括号.例:下面的例子FruitName注解就只有一个参数成员。

  • 元注解

  • 1.Target(目标)作用:用于描述注解的使用范围(即:被描述的注解可以用在什么地方)
    Target说明了Annotation所修饰的对象范围:Annotation可被用于 packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、
    方法参数和本地变量(如循环变量、catch参数)。在Annotation类型的声明中使用了target可更加明晰其修饰的目标。

  • 取值(ElementType)有:

  • -1.CONSTRUCTOR:用于描述构造器

    • 2.FIELD:用于描述域
  • -3.LOCAL_VARIABLE:用于描述局部变量

  • -4.METHOD:用于描述方法

  • -5.PACKAGE:用于描述包3

  • -6.PARAMETER:用于描述参数

  • -7.TYPE:用于描述类、接口(包括注解类型) 或enum声明

  • –elementType(元素类型) 可以有多个,一个注解可以为类的,方法的,字段的等等

  • 2.@Retention 作用:表示需要在什么级别保存该注释信息,用于描述注解的生命周期(即:被描述的注解在什么范围内有效)

  • Retention(保留)注解说明,这种类型的注解会被保留到那个阶段. 有三个值:

  • -1.RetentionPolicy.SOURCE —— 这种类型的Annotations只在源代码级别保留,编译时就会被忽略

  • -2.RetentionPolicy.CLASS —— 这种类型的Annotations编译时被保留,在class文件中存在,但JVM将会忽略

  • -3.RetentionPolicy.RUNTIME —— 这种类型的Annotations将被JVM保留,所以他们能在运行时被JVM或其他使用反射机制的代码所读取和使用.

  • 默认为 RetentionPolicy.CLASS

  • 3.@Documented,

  • Documented用于描述其它类型的annotation应该被作为被标注的程序成员的公共API,因此可以被例如javadoc此类的工具文档化。Documented是一个标记注解,没有成员。

  • 4.@Inherited

  • Inherited 元注解是一个标记注解,@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类型被发现,或者到达类继承结构的顶层。

实现自定义注解

  1. 创建注解接口:@注解名如:public @interface TestAnnotation{}

自定义注解1

@Retention(value=RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD})
public @interface TestAnnotation {
    //@TestAnnotation("xxxxxx") / @TestAnnotation(value ="xxxxxx")
    public String value() default "value默认值";

    //@TestAnnotation(name="xxxxxx")
    public String name() default "name默认值";
}

自定义注解2

@Retention(value=RUNTIME)
@Target({ElementType.TYPE,ElementType.METHOD})
public @interface TestAnnotation1 {
    //@TestAnnotation("xxxxxx") / @TestAnnotation(value ="xxxxxx")
    public String value() default "TestAnnotation1-value默认值";

    //@TestAnnotation(name="xxxxxx")
    public String name() default "TestAnnotation1-name默认值";
}

2.使用自定义注解

@TestAnnotation(value = "test")
public class TestAnnotationService {
}

3.使用反射技术获取自定义注解值

public class Test {
    public static void main(String[] arg) {
        try {
            //使用类路径进行反射
            Class<?> clazz = Class.forName("com.hairo.service.TestAnnotationService");
            //isAnnotationPresent判断Class是否声明TestAnnotation注解
            //System.out.println("@TestAnnotation是否存在:"+clazz.isAnnotationPresent(TestAnnotation.class));
            //返回此类存在的注解。
            for (Annotation annotated : clazz.getAnnotations()) {
                //输出注解类型
                System.out.println("TestAnnotationService类存在注解:"+annotated.annotationType());
            }

            System.out.println("******************************分割线**********************\n");
            //判断是否存在@TestAnnotation注解
            if(clazz.isAnnotationPresent(TestAnnotation.class)){
                Annotation annotation = clazz.getAnnotation(TestAnnotation.class);//获取TestAnnotation注解类
                //获取注解类的属性值
                System.out.println("@TestAnnotation**》name的值是:"+((TestAnnotation) annotation).name());
                //获取注解类的属性值
                System.out.println("@TestAnnotation**》value的值是:"+((TestAnnotation) annotation).value());
            }

            System.out.println("******************************分割线**********************\n");
            //判断是否存在@TestAnnotation1注解1
            if(clazz.isAnnotationPresent(TestAnnotation1.class)){
                Annotation annotation = clazz.getAnnotation(TestAnnotation1.class);//获取TestAnnotation注解类
                //获取注解类的属性值
                System.out.println("@TestAnnotation1--》name的值是:"+((TestAnnotation1) annotation).name());
                //获取注解类的属性值
                System.out.println("@TestAnnotation1--》value的值是:"+((TestAnnotation1) annotation).value());
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }
}

输出结果:
TestAnnotationService类存在注解:interface com.hairo.annotation.interfaceAnnotation.TestAnnotation
TestAnnotationService类存在注解:interface com.hairo.annotation.interfaceAnnotation.TestAnnotation1
********分割线

@TestAnnotation**》name的值是:自定义name
@TestAnnotation**》value的值是:TestAnnotation-value默认值
********分割线

@TestAnnotation1–》name的值是:TestAnnotation1-name默认值
@TestAnnotation1–》value的值是:自定义Value

PS:上述只是一个基于注解的入门,后续将会利用反射+自定义注解实现Spring ioc+aop+mvc等(基于注解方式无xml)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值