java 元注解_关于java自定义元注解Annotations分析&示例

一、前言

使用注解Annotations可以使代码开发变得更加的灵活多变,从另外一个维度降低了代码的复杂性和耦合度。现在新版本的JDK或主流Spring等框架扩展都提高了注解重要性,主要在java.lang.annotation包中实现,用来将任何的信息或元数据(metadata)与程序元素(类、方法、成员变量等)进行关联。

二、知识点&源码

注解主要作用:标记(用于告诉编译器一些信息)、编译时动态处理(动态生成代码)、运行时动态处理(得到注解信息)。分为两类:标准注解、元注解。

1. 标准注解

标准Annotation是指Java自带的几个Annotation,主要有@Override、@Deprecated、@SuppressWarnings

@Override@Target(ElementType.METHOD)@b@@Retention(RetentionPolicy.SOURCE)@b@public @interface Override {@b@}

@Deprecated@Documented@b@@Retention(RetentionPolicy.RUNTIME)@b@public @interface Deprecated {@b@}

@SuppressWarnings@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})@b@@Retention(RetentionPolicy.SOURCE)@b@public @interface SuppressWarnings {@b@    String[] value();@b@}

2. 元注解

元注解主要包含4个@Documented、@Inherited、@Retention、@Target,

@Documented - 所修饰的Annotation连同自定义Annotation所修饰的元素一同保存到Javadoc文档中@Documented@b@@Retention(RetentionPolicy.RUNTIME)@b@@Target(ElementType.ANNOTATION_TYPE)@b@public @interface Documented {@b@}

@Inherited - 是一个标记注解,可被继承关系的映射到(子类获取父类的注解Annotation信息)@Documented@b@@Retention(RetentionPolicy.RUNTIME)@b@@Target(ElementType.ANNOTATION_TYPE)@b@public @interface Inherited {@b@}

@Target - 修饰的对象范围,如 packages、types(类、接口、枚举、Annotation类型)、类型成员(方法、构造方法、成员变量、枚举值)、方法参数和本地变量

>ElementType.CONSTRUCTOR  作用于构造器

>ElementType.FIELD  作用于域/属性

>ElementType.LOCAL_VARIABLE  用于描述局部变量

>ElementType.METHOD  作用于方法

>ElementType.PACKAGE   用于描述包

>ElementType.PARAMETER   用于描述参数

>ElementType.TYPE   用于描述类、接口(包括注解类型) 或enum声明,最常用

>用法如下@Target(ElementType.TYPE)  @b@@Target({ ElementType.TYPE, ElementType.METHOD})

>源码@Documented@b@@Retention(RetentionPolicy.RUNTIME)@b@@Target(ElementType.ANNOTATION_TYPE)@b@public @interface Target {@b@    ElementType[] value();@b@}@b@public enum ElementType {@b@    /** Class, interface (including annotation type), or enum declaration */@b@    TYPE,@b@    /** Field declaration (includes enum constants) */@b@    FIELD,@b@    /** Method declaration */@b@    METHOD,@b@    /** Parameter declaration */@b@    PARAMETER,@b@    /** Constructor declaration */@b@    CONSTRUCTOR,@b@    /** Local variable declaration */@b@    LOCAL_VARIABLE,@b@    /** Annotation type declaration */@b@    ANNOTATION_TYPE,@b@    /** Package declaration */@b@    PACKAGE@b@}

@Retention - 描述注解的生命周期(即:被描述的注解在什么范围内有效)RetentionPolicy.RUNTIME //注解会在class字节码文件中存在,在运行时可以通过反射获取到@b@RetentionPolicy.CLASS //默认的保留策略,注解会在class字节码文件中存在,但运行时无法获得@b@RetentionPolicy.SOURCE //注解仅存在于源码中,在class字节码文件中不包含

>源码@Documented@b@@Retention(RetentionPolicy.RUNTIME)@b@@Target(ElementType.ANNOTATION_TYPE)@b@public @interface Retention {@b@    RetentionPolicy value();@b@}@b@public enum RetentionPolicy {@b@    /* Annotations are to be discarded by the compiler. */@b@    SOURCE,@b@    /* Annotations are to be recorded in the class file by the compiler@b@     * but need not be retained by the VM at run time.  This is the default@b@     * behavior. */@b@    CLASS,@b@    /* Annotations are to be recorded in the class file by the compiler and@b@     * retained by the VM at run time, so they may be read reflectively.@b@     * @see java.lang.reflect.AnnotatedElement */@b@    RUNTIME@b@}

三、自定义注解语法

1、格式定义

public @interface 注解名 {定义体}import java.lang.annotation.Documented;@b@import java.lang.annotation.ElementType;@b@import java.lang.annotation.Inherited;@b@import java.lang.annotation.Retention;@b@import java.lang.annotation.RetentionPolicy;@b@import java.lang.annotation.Target;@b@@b@@Documented@b@@Retention(RetentionPolicy.RUNTIME)@b@@Target(ElementType.METHOD)@b@@Inherited@b@public @interface MyMethod{@b@     String author() default "junni@xwood.net";@b@     String date();@b@     int version() default 1;@b@}

>说明

>>通过@interface 定义,注解名即为自定义注解名

>> 注解配置参数名为注解类的方法名

a)   所有方法没有方法体,方法名即为属性名,没有参数没有修饰符,实际只允许 public & abstract 修饰符,默认为 public ,不允许抛异常

b)  方法返回值只能是基本类型,String, Class, annotation, enumeration 或者是他们的一维数组,返回类型即为属性类型

c)  若只有一个默认属性,可直接用 value() 函数。一个属性都没有表示该 Annotation 为 Mark Annotation

d)  可以加 default 表示默认值,null不能作为成员默认值

2、调用public class MethodInvoker {@b@    @MyMethod( author ="xwood", date="2016/08/03", version=1)@b@    public String getName() {@b@        return "xwood.net";@b@    }@b@}

3. 测试类import java.lang.reflect.Method;@b@public class Test { @b@    public static void main(String[] args) throws NoSuchMethodException,SecurityException{@b@        Class clazz=MethodInvoker.class;@b@        Method method = clazz.getMethod("getName", new Class[]{});@b@        MyMethod myAnnotation = method.getAnnotation(MyMethod.class);  @b@        System.out.println("myAnnotation:"+myAnnotation.author()+";"+myAnnotation.date()+";"+myAnnotation.version());@b@    }@b@}

结果输出myAnnotation:xwood;2016/08/03;1

四、注释工具类

基于Spring的org.springframework.core.annotation.AnnotationUtils/*@b@ * Copyright 2002-2012 the original author or authors.@b@ *@b@ * Licensed under the Apache License, Version 2.0 (the "License");@b@ * you may not use this file except in compliance with the License.@b@ * You may obtain a copy of the License at@b@ *@b@ *      http://www.apache.org/licenses/LICENSE-2.0@b@ *@b@ * Unless required by applicable law or agreed to in writing, software@b@ * distributed under the License is distributed on an "AS IS" BASIS,@b@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.@b@ * See the License for the specific language governing permissions and@b@ * limitations under the License.@b@ */@b@@b@package org.springframework.core.annotation;@b@@b@import java.lang.annotation.Annotation;@b@import java.lang.reflect.AnnotatedElement;@b@import java.lang.reflect.Method;@b@import java.util.Arrays;@b@import java.util.Map;@b@import java.util.WeakHashMap;@b@@b@import org.springframework.core.BridgeMethodResolver;@b@import org.springframework.util.Assert;@b@@b@@b@public abstract class AnnotationUtils {@b@@b@@b@static final String VALUE = "value";@b@@b@private static final Map, Boolean> annotatedInterfaceCache = new WeakHashMap, Boolean>();@b@@b@public static  T getAnnotation(AnnotatedElement ae, Class annotationType) {@b@T ann = ae.getAnnotation(annotationType);@b@if (ann == null) {@b@for (Annotation metaAnn : ae.getAnnotations()) {@b@ann = metaAnn.annotationType().getAnnotation(annotationType);@b@if (ann != null) {@b@break;@b@}@b@}@b@}@b@return ann;@b@}@b@@b@@b@public static Annotation[] getAnnotations(Method method) {@b@return BridgeMethodResolver.findBridgedMethod(method).getAnnotations();@b@}@b@@b@@b@public static  A getAnnotation(Method method, Class annotationType) {@b@Method resolvedMethod = BridgeMethodResolver.findBridgedMethod(method);@b@A ann = resolvedMethod.getAnnotation(annotationType);@b@if (ann == null) {@b@for (Annotation metaAnn : resolvedMethod.getAnnotations()) {@b@ann = metaAnn.annotationType().getAnnotation(annotationType);@b@if (ann != null) {@b@break;@b@}@b@}@b@}@b@return ann;@b@}@b@@b@@b@public static  A findAnnotation(Method method, Class annotationType) {@b@A annotation = getAnnotation(method, annotationType);@b@Class> cl = method.getDeclaringClass();@b@if (annotation == null) {@b@annotation = searchOnInterfaces(method, annotationType, cl.getInterfaces());@b@}@b@while (annotation == null) {@b@cl = cl.getSuperclass();@b@if (cl == null || cl == Object.class) {@b@break;@b@}@b@try {@b@Method equivalentMethod = cl.getDeclaredMethod(method.getName(), method.getParameterTypes());@b@annotation = getAnnotation(equivalentMethod, annotationType);@b@}@b@catch (NoSuchMethodException ex) {@b@// No equivalent method found@b@}@b@if (annotation == null) {@b@annotation = searchOnInterfaces(method, annotationType, cl.getInterfaces());@b@}@b@}@b@return annotation;@b@}@b@@b@private static  A searchOnInterfaces(Method method, Class annotationType, Class>[] ifcs) {@b@A annotation = null;@b@for (Class> iface : ifcs) {@b@if (isInterfaceWithAnnotatedMethods(iface)) {@b@try {@b@Method equivalentMethod = iface.getMethod(method.getName(), method.getParameterTypes());@b@annotation = getAnnotation(equivalentMethod, annotationType);@b@}@b@catch (NoSuchMethodException ex) {@b@// Skip this interface - it doesn't have the method...@b@}@b@if (annotation != null) {@b@break;@b@}@b@}@b@}@b@return annotation;@b@}@b@@b@private static boolean isInterfaceWithAnnotatedMethods(Class> iface) {@b@synchronized (annotatedInterfaceCache) {@b@Boolean flag = annotatedInterfaceCache.get(iface);@b@if (flag != null) {@b@return flag;@b@}@b@boolean found = false;@b@for (Method ifcMethod : iface.getMethods()) {@b@if (ifcMethod.getAnnotations().length > 0) {@b@found = true;@b@break;@b@}@b@}@b@annotatedInterfaceCache.put(iface, found);@b@return found;@b@}@b@}@b@@b@@b@public static  A findAnnotation(Class> clazz, Class annotationType) {@b@Assert.notNull(clazz, "Class must not be null");@b@A annotation = clazz.getAnnotation(annotationType);@b@if (annotation != null) {@b@return annotation;@b@}@b@for (Class> ifc : clazz.getInterfaces()) {@b@annotation = findAnnotation(ifc, annotationType);@b@if (annotation != null) {@b@return annotation;@b@}@b@}@b@if (!Annotation.class.isAssignableFrom(clazz)) {@b@for (Annotation ann : clazz.getAnnotations()) {@b@annotation = findAnnotation(ann.annotationType(), annotationType);@b@if (annotation != null) {@b@return annotation;@b@}@b@}@b@}@b@Class> superClass = clazz.getSuperclass();@b@if (superClass == null || superClass == Object.class) {@b@return null;@b@}@b@return findAnnotation(superClass, annotationType);@b@}@b@@b@@b@public static Class> findAnnotationDeclaringClass(Class extends Annotation> annotationType, Class> clazz) {@b@Assert.notNull(annotationType, "Annotation type must not be null");@b@if (clazz == null || clazz.equals(Object.class)) {@b@return null;@b@}@b@return (isAnnotationDeclaredLocally(annotationType, clazz)) ? clazz :@b@findAnnotationDeclaringClass(annotationType, clazz.getSuperclass());@b@}@b@@b@@b@public static boolean isAnnotationDeclaredLocally(Class extends Annotation> annotationType, Class> clazz) {@b@Assert.notNull(annotationType, "Annotation type must not be null");@b@Assert.notNull(clazz, "Class must not be null");@b@boolean declaredLocally = false;@b@for (Annotation annotation : Arrays.asList(clazz.getDeclaredAnnotations())) {@b@if (annotation.annotationType().equals(annotationType)) {@b@declaredLocally = true;@b@break;@b@}@b@}@b@return declaredLocally;@b@}@b@@b@@b@public static boolean isAnnotationInherited(Class extends Annotation> annotationType, Class> clazz) {@b@Assert.notNull(annotationType, "Annotation type must not be null");@b@Assert.notNull(clazz, "Class must not be null");@b@return (clazz.isAnnotationPresent(annotationType) && !isAnnotationDeclaredLocally(annotationType, clazz));@b@}@b@@b@@b@public static Map getAnnotationAttributes(Annotation annotation) {@b@return getAnnotationAttributes(annotation, false, false);@b@}@b@@b@@b@public static Map getAnnotationAttributes(Annotation annotation, boolean classValuesAsString) {@b@return getAnnotationAttributes(annotation, classValuesAsString, false);@b@}@b@@b@@b@public static AnnotationAttributes getAnnotationAttributes(@b@Annotation annotation, boolean classValuesAsString, boolean nestedAnnotationsAsMap) {@b@@b@AnnotationAttributes attrs = new AnnotationAttributes();@b@Method[] methods = annotation.annotationType().getDeclaredMethods();@b@for (Method method : methods) {@b@if (method.getParameterTypes().length == 0 && method.getReturnType() != void.class) {@b@try {@b@Object value = method.invoke(annotation);@b@if (classValuesAsString) {@b@if (value instanceof Class) {@b@value = ((Class>) value).getName();@b@}@b@else if (value instanceof Class[]) {@b@Class>[] clazzArray = (Class[]) value;@b@String[] newValue = new String[clazzArray.length];@b@for (int i = 0; i  annotationType) {@b@return getDefaultValue(annotationType, VALUE);@b@}@b@@b@@b@public static Object getDefaultValue(Class extends Annotation> annotationType, String attributeName) {@b@try {@b@Method method = annotationType.getDeclaredMethod(attributeName, new Class[0]);@b@return method.getDefaultValue();@b@}@b@catch (Exception ex) {@b@return null;@b@}@b@}@b@@b@}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值