1.什么是Java注解
- 是在 JDK5 时引入的新特性,其实就是代码里的特殊标记
- 注解也被称为元数据, 是附加在代码中的一些元信息,用于一些工具在编译、运行时进行解析和使用
- 允许开发人员在不改变源代码的情况下,在源代码中添加一些元数据
- 以便让编译器或者其他工具可以读取这些元数据,从而实现更高级的功能
- 应用场景丰富
- 生成文档
- 编译时进行格式检查,如@Override
- 替代配置文件功能,比如spring的注解
- 和反射组合应用,自己封装框架组件
- 注解的声明@interface
- 用来声明一个注解,可以通过default来声明参数的默认值
- 自定义注解时,自动继承了java.lang.annotation.Annotation接口
- 通过反射可以获取自定义注解
public @interface Test { }
2.Java注解类型
- Java自带的标准注解(这些注解后编译器就会进行检查)
- @Override 标记覆写父类的方法
- @Deprecated 标记被修饰的类或类成员、类方法已废弃、过时
- @SuppressWarnings 用于关闭对类、方法、成员编译时产生的特定警告。
- 元注解(用于定义注解的注解)
- 元注解也是Java自带的标准注解,只不过用于修饰注解,比较特殊。
- @Retention、@Target、@Inherited、@Documented、@Repeatable
- java内置4种元注解
- @Target表示该注解用于什么地方
- ElementType.CONSTRUCTOR 用在构造器
- ElementType.FIELD 用于描述域-属性上
- ElementType.METHOD 用在方法上
- ElementType.TYPE 用在类或接口上
- ElementType.PACKAGE 用于描述包
- @Retention 表示在什么级别保存该注解信息
- RetentionPolicy.SOURCE 保留到源码上
- RetentionPolicy.CLASS 保留到字节码上
- RetentionPolicy.RUNTIME 保留到虚拟机运行时(最多,可通过反射获取)
- @Documented 将此注解包含在 javadoc 中
- @Inherited 是否允许子类继承父类中的注解
- 用户可以根据自己的需求定义注解
3.自定义注解案例实战
- 需求
- 实现一个类似junit单元测试的注解,可以批量运行某个类的全部加了注解的方法
- 需要支持支持自定义优先级执行,且支持不测试某个方法的开关
- 知识点
- 反射上面获取自定义注解,作用范围 Class 、Method、Field都支持
方法 | 说明 |
getAnnotations( ) | 获取类、方法等上的所有注解内容 |
getAnnotation(XXX.class) | 获取到注解的内容 |
isAnnotationPresent(XXX.class) | 判断某个注解是否存在 |
- 编码实战
- 定义注解类
//包含在DOC中 @Documented //允许子类继承父类中的注解 @Inherited //作用在方法上 @Target(ElementType.METHOD) //保留到JVM运行上 @Retention(RetentionPolicy.RUNTIME) public @interface Test { //定义优先级,默认是0 int priority() default 0; //是否要禁用,默认是false boolean disabled() default false; }
- 定义目标类
public class MainTest { @Test(priority = 1) public void test1(){ System.out.println("执行test1()...."); } @Test(priority = 2) public void test2(){ System.out.println("执行test2()...."); } @Test(priority = 3) public void test3(){ System.out.println("执行test3()...."); } @Test(priority = 4) public void test4(){ System.out.println("执行test4()...."); } }
- 定义测试类
public class TestCore { public static void main(String[] args) throws InstantiationException, IllegalAccessException { Class<MainTest> mainTestClass = MainTest.class; //创建 MainTest 对象 MainTest mainTest = mainTestClass.newInstance(); //获取MainTest中所有的方法 Method[] declaredMethods = mainTestClass.getDeclaredMethods(); //定义Method集合 List<Method> methods = new ArrayList<>(); //过滤是否有禁用执行的方法 for (Method declaredMethod : declaredMethods) { Test annotation = declaredMethod.getAnnotation(Test.class); if(!annotation.disabled()){ methods.add(declaredMethod); }; } //对list中的数据进行排序,按照优先级执行 methods.sort(Comparator.comparingInt(obj->obj.getAnnotation(Test.class).priority())); //遍历集合执行方法 methods.forEach(method -> { try { method.invoke(mainTest); } catch (Exception e) { System.out.println("执行方法失败"); } }); } }