首页 > 代码库 > 自定义注解的实现

自定义注解的实现

  注解看起来很神秘,其实看穿了就是一种标记,通过运行时获取标记进行后续处理。说到运行时自然离不开反射,所以注解就是反射的一种应用。使用元注解就可以实现自定义注解,元注解只有4个:Retention、Target、Document和Inherited,分别用于标记注解的保留策略、应用目标、是否包含于javadoc、是否允许子类继承。直接看代码:

package com.wulinfeng.annotation;

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.TYPE)
public @interface Type {

    String name() default "";
}
package com.wulinfeng.annotation;

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 Element {

    String value() default "";
}
package com.wulinfeng.annotation;

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 MethodName {

    int version() default 0; 
}
package com.wulinfeng.annotation;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.TreeMap;

@Type(name = "hello")
public class Annotations {

    Map<Integer, Method> methodMap = new TreeMap<>();

    @Element("world")
    private String name;

    @MethodName(version = 1)
    public void logs1(Class<?> clazz) {

        // 取类注释值
        for (Annotation annotation : clazz.getAnnotations())
            if (annotation instanceof Type) {
                name = ((Type) annotation).name();
                break;
            }

        System.out.println("hello " + name);
    }

    @MethodName(version = 2)
    public void logs2(Class<?> clazz) {

        // 取字段name的注解值
        Field[] fields = Annotations.class.getDeclaredFields();
        for (Field field : fields) {
            if (field.isAnnotationPresent(Element.class)) {
                Element element = field.getAnnotation(Element.class);
                name = element.value();
                break;
            }
        }

        System.out.println("hello " + name);
    }

    // 加载方法版本号映射
    public void initialize(Class<?> clazz) {
        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            for (Annotation annotation : method.getAnnotations()) {
                if (annotation instanceof MethodName) {
                    methodMap.put(((MethodName) annotation).version(), method);
                }
            }
        }
    }

    // 根据方法版本号获取具体方法,通过反射执行方法
    public void execute(int version, Class<?> clazz)
            throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {
        Method method = methodMap.get(version);

        Object o = clazz.newInstance();
        if (method != null) {
            method.invoke(o, clazz);
        }
    }

    public static void main(String[] args)
            throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException {

        // 开始测试不同版本号的方法调用
        Annotations annotation = new Annotations();
        annotation.initialize(Annotations.class);
        annotation.execute(1, Annotations.class);
        annotation.execute(2, Annotations.class);
    }
}

 运行结果:

hello hello
hello world

 

自定义注解的实现