1、结合反射使用

此种方法主要是在使用一些框架时,通过定义注解来实现对配置文件的读取,而不需要在读取本地配置文件

在程序使用(解析)注解:获取注解中定义的属性值

  1. 获取注解定义的位置的对象 (Class,Method,Field)
  2. 获取指定的注解
    • getAnnotation(Class)
      //其实就是在内存中生成了一个该注解接口的子类实现对象
      1. public class ProImpl implements Pro{
      2. public String className(){
      3. return "cn.itcast.annotation.Demo1";
      4. }
      5. public String methodName(){
      6. return "show";
      7. }
      8. }
  1. 调用注解中的抽象方法获取配置的属性值

代码示例

  1. /**
  2. * 框架类
  3. */
  4. @Target({ElementType.TYPE})
  5. @Retention(RetentionPolicy.RUNTIME)
  6. public @interface Pro {
  7. String className();
  8. String methodName();
  9. }
  10. @Pro(className = "cn.itcast.annotation.Demo1",methodName = "show")
  11. public class ReflectTest {
  12. public static void main(String[] args) throws Exception {
  13. /*
  14. 前提:不能改变该类的任何代码。可以创建任意类的对象,可以执行任意方法
  15. */
  16. //1.解析注解
  17. //1.1获取该类的字节码文件对象
  18. Class<ReflectTest> reflectTestClass = ReflectTest.class;
  19. //2.获取上边的注解对象
  20. //其实就是在内存中生成了一个该注解接口的子类实现对象
  21. /*
  22. public class ProImpl implements Pro{
  23. public String className(){
  24. return "cn.itcast.annotation.Demo1";
  25. }
  26. public String methodName(){
  27. return "show";
  28. }
  29. }
  30. */
  31. Pro an = reflectTestClass.getAnnotation(Pro.class);
  32. //3.调用注解对象中定义的抽象方法,获取返回值
  33. String className = an.className();
  34. String methodName = an.methodName();
  35. System.out.println(className);
  36. System.out.println(methodName);
  37. //3.加载该类进内存
  38. Class cls = Class.forName(className);
  39. //4.创建对象
  40. Object obj = cls.newInstance();
  41. //5.获取方法对象
  42. Method method = cls.getMethod(methodName);
  43. //6.执行方法
  44. method.invoke(obj);
  45. }
  46. }

2、简单测试框架

需求:测试计算器类中的方法是否出错;

常规思路,创建calculator类的实例,依次调用方法,看是否出错,此方法较为麻烦;

使用注解后,可通过反射的方法,获取calculator类的所有方法,同时通过判断是否有注解,进行测试,较为方便快捷

Calculator类

  1. /**
  2. * 小明定义的计算器类
  3. */
  4. public class Calculator {
  5. //加法
  6. @Check
  7. public void add(){
  8. String str = null;
  9. str.toString();
  10. System.out.println("1 + 0 =" + (1 + 0));
  11. }
  12. //减法
  13. @Check
  14. public void sub(){
  15. System.out.println("1 - 0 =" + (1 - 0));
  16. }
  17. //乘法
  18. @Check
  19. public void mul(){
  20. System.out.println("1 * 0 =" + (1 * 0));
  21. }
  22. //除法
  23. @Check
  24. public void div(){
  25. System.out.println("1 / 0 =" + (1 / 0));
  26. }
  27. public void show(){
  28. System.out.println("永无bug...");
  29. }
  30. }

check注解

  1. import java.lang.annotation.ElementType;
  2. import java.lang.annotation.Retention;
  3. import java.lang.annotation.RetentionPolicy;
  4. import java.lang.annotation.Target;
  5. @Retention(RetentionPolicy.RUNTIME)
  6. @Target(ElementType.METHOD)
  7. public @interface Check {
  8. }

测试类

  1. import java.io.BufferedWriter;
  2. import java.io.FileWriter;
  3. import java.io.IOException;
  4. import java.lang.reflect.InvocationTargetException;
  5. import java.lang.reflect.Method;
  6. /**
  7. * 简单的测试框架
  8. *
  9. * 当主方法执行后,会自动自行被检测的所有方法(加了Check注解的方法),判断方法是否有异常,记录到文件中
  10. */
  11. public class TestCheck {
  12. public static void main(String[] args) throws IOException {
  13. //1.创建计算器对象
  14. Calculator c = new Calculator();
  15. //2.获取字节码文件对象
  16. Class cls = c.getClass();
  17. //3.获取所有方法
  18. Method[] methods = cls.getMethods();
  19. int number = 0;//出现异常的次数
  20. BufferedWriter bw = new BufferedWriter(new FileWriter("bug.txt"));
  21. for (Method method : methods) {
  22. //4.判断方法上是否有Check注解
  23. if(method.isAnnotationPresent(Check.class)){
  24. //5.有,执行
  25. try {
  26. method.invoke(c);
  27. } catch (Exception e) {
  28. //6.捕获异常
  29. //记录到文件中
  30. number ++;
  31. bw.write(method.getName()+ " 方法出异常了");
  32. bw.newLine();
  33. bw.write("异常的名称:" + e.getCause().getClass().getSimpleName());
  34. bw.newLine();
  35. bw.write("异常的原因:"+e.getCause().getMessage());
  36. bw.newLine();
  37. bw.write("--------------------------");
  38. bw.newLine();
  39. }
  40. }
  41. }
  42. bw.write("本次测试一共出现 "+number+" 次异常");
  43. bw.flush();
  44. bw.close();
  45. }
  46. }