java 编程基础:【注解】 提取注解信息,利用自定义注解编写测试类,注解绑定事件

提取注解信息

使用注解修饰了类、方法、成员变量等成员之后,这些注解不会自己生效,必须由开发者提供相应工具来提取并处理注解信息。
 
Java使用java.lang.annotation.Annotation接口代表程序元素前面的注解,该接口是所有注解的父接口。Java5在java.lang.reflect包下新增了AnnotatedElement接口,该接口代表程序中可以接受注解程序元素(就是哪些类可以被注解修饰)。该接口主要有如下几个实现类。
  • Class: 类定义
  • Constructor: 构造器定义
  • Field: 类的成员变量定义
  • Method: 类的方法定义
  • Packag: 的包定义
 
对于AnnotatedElement的实现类,Java提供了如下几个方法来获取修饰其的注解的信息:
 
先定义一个注解,可以在运行的时候获取到:
package com.zmd.myAnnotation;
import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME) //配置生命周期运行时可以获取到
@Inherited //配置注解的继承性,用了注解的父类,子类默认被修饰
public @interface MyAnnotation {
    String name() default "zmd";
    int age() default 22;
}

定义一个父类使用注解

package com.zmd.myAnnotation;

import java.lang.annotation.Annotation;

@MyAnnotation(name = "hehe",age = 1)
public class MyClass {
    public static void main(String[] args) {
        //判断是否有MyAnnotation注解修饰
        System.out.println(MyClass.class.isAnnotationPresent(MyAnnotation.class)); //true
        //获取包括继承父类的注解。
        Annotation annotation = MyClass.class.getAnnotation(MyAnnotation.class);
        if (annotation instanceof MyAnnotation){
            MyAnnotation myAnnotation = (MyAnnotation) annotation;
            System.out.println("tag is:" + annotation);  //tag is:@com.zmd.myAnnotation.MyAnnotation(name="hehe", age=1)
            System.out.println("name is:" + myAnnotation.name()); //name is:hehe
            System.out.println("age is:" + myAnnotation.age()); //age is:1
        }
    }
}

定义子类继承父类获取注解信息

package com.zmd.myAnnotation;
import java.lang.annotation.Annotation;

public class MySubClass extends MyClass {
    public static void main(String[] args) {
        //是不是有MyAnnotation注解修饰
        System.out.println(MySubClass.class.isAnnotationPresent(MyAnnotation.class)); //true
        //获取指定类型的Annotation
//        Annotation annotation = SubClass.class.getAnnotation(MyAnnotation.class);//用这行代码,可以获取到MyAnnotation,因为MyAnnotation是获取所有包括继承性的
        Annotation annotation = MySubClass.class.getDeclaredAnnotation(MyAnnotation.class);//用这行代码无法获取到MyAnnotation,因为我们getDeclaredAnnotation方法只能获取到直接修饰该类的注解,不能获取到从父类继承过来的注解
        System.out.println(annotation); //null
        if (annotation instanceof MyAnnotation) { //false 啥也没输出
            System.out.println("tag is " + annotation);
            System.out.println("name is " + ((MyAnnotation) annotation).name());
            System.out.println("age is " + ((MyAnnotation) annotation).age());
        }
    }
}

编写测试工具

利用自定义注解标识可测试的方法,编写测试工具类,用于测试那些只标识了可以测试的方法

1、编写自定义注解

package com.zmd.autotestTools;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME) //运行时可获取
@Target(ElementType.METHOD) //只能修饰方法
public @interface Testable {
}

2、编写使用注解的类

package com.zmd.autotestTools;

public class MyClass {
    @Testable
    public static void m1() {};

    public static void m2() {};

    @Testable
    public static void m3() {throw new RuntimeException();};

    public static void m4() {};

    @Testable
    public static void m5() {throw new IllegalArgumentException();};

    public static void m6() {};

    @Testable
    public static void m7() {};

    public static void m8() {};
}

3、编写工具类测试 使用注解的类中的方法

package com.zmd.autotestTools;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

/**
 * @ClassName TestMethod
 * @projectName: object1
 * @author: Zhangmingda
 * @description: XXX
 * date: 2021/5/18.
 */
public class TestMethod {
    public static void test(Class<?> cls) throws IllegalAccessException, InstantiationException {
        //获取所有的方法
        Method[] methods = cls.getMethods();
        //创建一个实例
        MyClass myClass = (MyClass) cls.newInstance();
        for (Method method : methods){
            //如果方法被修饰,意思是可以测试
            if (method.isAnnotationPresent(Testable.class)){
                //那就测试
                try {
                    //如果是静态方法
                    if (Modifier.isStatic(method.getModifiers())){
                        method.invoke(null);
                    }else {
                        method.invoke(MyClass.class);
                    }
                    System.out.println(method.getName() + "测试成功");
                }catch (InvocationTargetException e) {
//                    e.printStackTrace();
                    System.err.println(method.getName() + "测试失败");
                }

            }
        }
    }

    public static void main(String[] args) throws InstantiationException, IllegalAccessException {
        test(MyClass.class);
    }
}

 注解绑定事件

开发思路:

  • 1、定义单独一个处理注解的类,使用此类的静态方法处理给定对象中的所有实例变量。
  • 2、自定义注解中定义属性,用于使用注解时传入对应的事件类型。
  • 3、窗口Button使用注解,再调用处理注解的类处理窗口中所有实例变量。

1、编写自定义注解

package com.zmd.annotationbindAction;

import java.awt.event.ActionListener;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)//运行时可获取
@Target(ElementType.FIELD) //只能修饰类变量实例变量
public @interface ActionListenFor {
    Class<? extends ActionListener>  value();
}

2、编写绑定事件方法类

package com.zmd.annotationbindAction;

import javax.swing.*;
import java.awt.event.ActionListener;
import java.lang.reflect.Field;
import java.lang.reflect.Type;

/**
 * @ClassName ProcessesAnnotation
 * @projectName: object1
 * @author: Zhangmingda
 * @description: 处理
 * date: 2021/5/18.
 */
public class ProcessesAnnotation {
    public static void processes(Object object) throws IllegalAccessException, InstantiationException {
        Class<?> cls = object.getClass();
        //获取所有属性
        Field[] allField = cls.getDeclaredFields();
        for (Field field : allField) {
            //如果属性被注解修饰
            if (field.isAnnotationPresent(ActionListenFor.class)){
                //设置可访问
                field.setAccessible(true);
                //获取对应的注解
                ActionListenFor actionListenFor = field.getAnnotation(ActionListenFor.class);
                //获取要绑定的事件的Class,创建事件监听器
                Class<? extends ActionListener> actionClass = actionListenFor.value();
                ActionListener actionListener = actionClass.newInstance();
                //将属性转换为button对象绑定事件
                AbstractButton button = (AbstractButton) field.get(object);
                button.addActionListener(actionListener);
            }
        }
    }
}

2、编写图形化窗口

package com.zmd.annotationbindAction;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

/**
 * @ClassName TestAnnotationBindAction
 * @projectName: object1
 * @author: Zhangmingda
 * @description: XXX
 * date: 2021/5/18.
 */
public class TestAnnotationBindAction {

    //定义窗口需要的基础属性
    private JFrame jFrame = new JFrame("测试注解绑定事件");

    @ActionListenFor(okAction.class)
    private JButton confirmbutton = new JButton("确定");

    @ActionListenFor(cancleAction.class)
    private JButton canclebutton = new JButton("取消");

    private JPanel jPanel = new JPanel();

    /**
     * 组装窗口
     */
    private void  start() throws InstantiationException, IllegalAccessException {
        jPanel.add(confirmbutton);
        jPanel.add(canclebutton);
        jFrame.add(jPanel);
        jFrame.setLocation(400,300);
        jFrame.pack();
        jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        jFrame.setVisible(true);
        //使用处理类处理本类所有属性
        ProcessesAnnotation.processes(this);
    }

    public static class okAction implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent actionEvent) {
            System.out.println("点击了确认按钮");
        }
    }
    public static class cancleAction implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent actionEvent) {
            System.out.println("点击了取消按钮");
        }
    }
    public static void main(String[] args) throws IllegalAccessException, InstantiationException {
        new TestAnnotationBindAction().start();
    }
}

 

 

 

 

posted on 2021-05-18 20:00  zhangmingda  阅读(343)  评论(0编辑  收藏  举报

导航