Java注解的诱惑

遗失的藏宝图.

1、JDK中预定义的一些注解

@Override : 检测被该注解标注的方法是否继承自父类

@Deprecated : 该注解标注的内容,表示已过时

@SuppressWarnings : 压制警告
一般传递参数all @SuppressWarnings(“all”)

2、自定义注解

  1. 格式
元注解
public @interface MyAnoo {
    属性列表
}   
  1. 本质
//通过 javap myAnoo.class 反编译可以得到
public interface com.yhw.MyAnoo extends java.lang.annotation.Annotation {}
//所以本质上注解就是个接口,默认继承Annotation
  1. 属性
- 接口中可以定义什么,注解中也可以
- 属性就是接口中抽象方法
// 要求
    1.属性的返回值类型有下列取值
    	基本数据类型
    	String
    	枚举
    	注解
    	以上类型的数组
    2.定义了属性,在使用时需要给属性赋值
      1.如果定义属性时,使用default关键字给属性默认初始化值,则使用注解时,可以不给属性赋值
      2.如果只有一个属性需要赋值,并且属性的名称是value,则value可以省略,直接定义值即可
      3.数组赋值时,值使用{}包裹。如果数组中只有一个值,则{}可以省略  
  1. 元注解
// 用于描述注解的注解
常见的
    1.@Target:描述注解能够作用的位置 
        ElementType.TYPE 作用在类上
        ElementType.METHOD 作用在方法上
        ElementType.FIELD 作用在变量上
    2.@Retention:描述被描述的注解被保留的阶段  硬盘 内存 运行时
        RetentionPolicy.RUNTIME 当前被描述的注解,会保留到class字节码中,并被JVM读取到
    3.@Documented:描述注解是否被抽取到api文档中
    4.@Inherited:描述注解是否被子类继承         
        
  1. 举例
//依次作用在类、方法、变量上
@Target({ElementType.TYPE,ElementType.METHOD,ElementType.FIELD})
//在程序运行时生效
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnoo {
    int value() default 18 ;
    Person per();
    String name() default "张三";
    String[] strs();
}   
public class Person {
    private String name;
    private int age;

    public void eat() {
        System.out.println("吃啥呢??");
    }
}
@MyAnoo(value=12,per=Person1,strs="史莱克")
public class Woreker{
    
}

3、解析注解

3.1、步骤

1 获取被加注解的位置的对象
	由于注解可以加在 类 成员方法 成员变量上
	对应的 可以 获得 Class Method Filed 对象
2 获取指定的注解
	getAnnotation(Class 注解名)
	//其实就是在内存中生成了一个该注解接口的子类实现对象
        /*
         public class MyAnooImpl implements MyAnno{

           pubic String className(){

                 return "com.yhw.pojo.Person"
            }
           pubic String classMethod(){}
                 return "eat"
            }
         */
3 调用注解中的抽象方法获取配置的属性值	
	

3.2、简单实现

  • pojo
public class Person {
    private String name;
    private int age;

    public void eat() {
        System.out.println("吃啥呢??");
    }
}
  • 注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyAnoo {

    String className();
    String classMethod();

}
  • 测试
import java.lang.reflect.Method;

@MyAnoo(classMethod = "eat", className = "com.yhw.pojo.Person")
public class ReflectTest2 {
    public static void main(String[] args) throws Exception {

        //1.获取当前类的字节码文件
        Class<ReflectTest2> aClass = ReflectTest2.class;

        //2.获取注解对象
        //其实就是在内存中生成了一个该注解接口的子类实现对象
        /*
         public class MyAnooImpl implements MyAnno{

           pubic String className(){

                 return "com.yhw.pojo.Person"
            }
           pubic String classMethod(){}
                 return "eat"
            }
         */

        MyAnoo myAn = aClass.getAnnotation(MyAnoo.class);

        //3.调用注解对象中定义的抽象方法,获取返回值
        String className = myAn.className();
        String classMethod = myAn.classMethod();

        System.out.println(classMethod);
        System.out.println(className);

        //4.通过反射实例化对象,调用方法

        //通过类的全路径加载类的Class对象
        Class clazz = Class.forName(className);

        //通过Class对象new一个实例
        Object newInstance = clazz.newInstance();

        //通过类的Class对象得到方法对象
        Method method = clazz.getMethod(classMethod);

        //通过得到方法对象invoke实例对象,实现方法的调用
        Object obj = method.invoke(newInstance);


    }
}

4、测试框架

通过给要测试的对象方法上加注解,达到自动测试效果,输出测试文件

  1. 被测试类
public class Calculator {

    @Check
    public void add() {
        System.out.println("1 + 0 =" + (1 + 0));
    }

    @Check
    public void sub() {
        System.out.println("1 - 0 =" + (1 - 0));
    }

    @Check
    public void mul() {
        System.out.println("1 * 0 =" + (1 * 0));
    }

    @Check
    public void div() {
        System.out.println("1 / 0 =" + (1 / 0));
    }

    public void show() {
        System.out.println("看看你");
    }
}
  1. 注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

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

}
  1. 测试
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.lang.reflect.Method;

public class TestCheck {

    public static void main(String[] args) throws Exception {

        //1.创建要测试的类对象
        Calculator cal = new Calculator();

        //2.得到对象的方法对象
        Method[] methods = cal.getClass().getMethods();

        int number = 0; //出现异常的次数

        BufferedWriter bw = new BufferedWriter(new FileWriter("bug.txt"));

        //3.判断方法上是否有Check注解
        for (Method method : methods) {
            //4如果有注解则执行方法,抓取异常
            if (method.isAnnotationPresent(Check.class)) {
                //5有就执行
                try {
                    method.invoke(cal);
                } catch (Exception e) {
                    //6捕获异常
                    //记录到文件中

                    number++;

                    bw.write(method.getName() + "方法出现异常了");
                    bw.newLine();
                    //通过得到异常对象,再通过字节码对象得到类名
                    bw.write("异常的名字" + e.getCause().getClass().getSimpleName());
                    bw.newLine();
                    bw.write("异常的原因" + e.getCause().getMessage());
                    bw.newLine();
                    bw.write("-------------------------------");
                    bw.newLine();
                }
            }
        }

        bw.write("本次测试一共出现" + number + "次异常");

        bw.flush();
        bw.close();

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值