`

Java自定义注解(原理和API)初探

阅读更多

    今天稍稍学习了下注解,关于注解,我想大家都不陌生,目前可能在hibernate配置中可能会用的多一点,在JPA中也会用到。我想说的是学习注解可以帮助我们更好的理解注解在框架中(比如hibernate和Spirng等)的应用。

    Annotation是JDK5版本以来的新特性。目前在JavaSE中的学习中可能会经常遇到集合未指定泛型、使用java.util.Date类中的过时方法,编译器给出warning时,均可以采用增加注解如(SuppressWarnings("unchecked")),Deprecated等来消除警告,这样看起来会好看些。

    好,下面开始进入重点学习,首先做下说明,学习Annotation时最好先了解下JDK的反射机制,关于JDK反射机制的学习,大家可以参考我之前发表的两篇博客(1. 反射初探:http://xiaoyun34286136.iteye.com/blog/190423, 2. 使用反射对类的私有方法和私有属性进行调用和修改:http://xiaoyun34286136.iteye.com/blog/1908554)。

    学习Annotation涉及到的java类包含:java.lang.annotation.Annotation。所有定义的annotation均默认实现了Annotation接口,但是要注意的是,实现Annotation接口的类并不是annotation。

    java中的annotation中包含的注解类型有Documented,Inherited,Retention,Target,其中常用的有Inherited(子类可以继承父类的注解),Retention(注解类型要保留多久,可否利用反射机制调用等),Target(注解的作用对象,类,接口,方法,属性等)。定义注解的关键字为@interface,关于JDK1.6自带的注解比如SuppressWarnings("unchecked")),Deprecated等我就不介绍了,相信有一定基础的都遇到过。

    相信在诸如hibernate和spring等框架中,我相信这些框架是使用反射读取的注解及注解中的参数,根据这些注解和参数通过一定的逻辑来对业务进行控制的。

    下面开始自定义一个注解并讲解使用,具体步骤为:

    定义注解->写测试类->进行测试

一、定义注解:

注解一:AnnotationTest

@Retention(RetentionPolicy.RUNTIME) // 将Retention的值设置为RetentionPolicy.RUNTIME,这样就可以在程序运行期间可以用反射对注解进行解析,设置为CLASS何SOURCE均不能
public @interface AnnotationTest {
 String value() default "good";
 String value1() default "hello";
 EnumTest value2(); //枚举类型
}
/**
 * 自定义枚举类
 *
 * @author XiaoYun 2013-07-20
 */
enum EnumTest {
 HELLO, world, welcome
}

注解二:

MyAnnotation.java
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

/**
 * 自定义注解
 *
 * @author XiaoYun 2013-07-20
 */
@Retention(RetentionPolicy.CLASS)//将Retention的值设置为RetentionPolicy.CLASS,程序运行的时候就不能通过反射解析
public @interface MyAnnotation {
 String value() default "hello";
 String hello();
 String world();
}

测试类(这里为了少写一个类,就把测试方法和类放到了一个类中):MyTest.java

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

@AnnotationTest(value1="hello", value2=EnumTest.world)
@MyAnnotation(world="world", hello="hello")
public class MyTest {
 
 @MyAnnotation(world="world", hello="hello")
 private String field;
 
 @AnnotationTest(value1="hello", value2=EnumTest.world)
 @MyAnnotation(value="xiaoyun", hello="hello", world="world")
 private void method() {  
  System.out.println("field的值为:" + field + "\nmethod from MyTest!");
 }
 
 @Override
 public String toString() {
  return "MyTest [field=" + field + "]";
 }

 /**
  * 测试方法
  * @param args
  */
 public static void main(String[] args) throws Exception {
  // 实例化对象
  MyTest test = new MyTest();
  // 获取Class类型
  Class cls = MyTest.class;
  // 根据方法名获取方法
  Method method = cls.getDeclaredMethod("method", null);
  // 获取属性
  Field field = cls.getDeclaredField("field");
  // 判断如果该方法中包含有MyAnnotation类型的注解,则进行如下操作
  if (method.isAnnotationPresent(AnnotationTest.class)) {
   // 取消Java访问性检查
   field.setAccessible(true);
   method.setAccessible(true);
   // 给test对象上的field属性赋值,并执行method方法
   field.set(test, "我是肖云,大家好!");
   method.invoke(test, null);
   
   // 根据注解类型获取特定的注解并打印到控制台
   Annotation annotation = method.getAnnotation(AnnotationTest.class);
   System.out.println(annotation.annotationType() + "\n" + annotation.annotationType().getName());
  }
  
  // 获取所有的注解并逐次迭代(这需要注解中Retention中的value为RetentionPolicy.Runntime)
  Annotation[] annotations = method.getAnnotations();
  if (annotations.length > 0) {
   System.out.println("------------打印所有注解--------------");
   for (Annotation annotation : annotations) {
    System.out.println(annotation.annotationType().getCanonicalName());
   }
  }
 }
}
    上面一个例子主要说明的是java.lang.annotation.Annotation接口中的Retention属性(JVM是否保留注释,是否可用反射读取)TargetAnnotationDemo ,接下来第二个例子用到了剩下的三个属性(Documented(不是重点,生成API文档时用),Target,Inherited),下面开始介绍:

首先还是定义注解:

TargetAnnotationDemo.java

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

/**
 * @Target注解
 *
 * @author XiaoYun 2013-07-20
 */
@Target({ElementType.TYPE, ElementType.METHOD})  //程序类型的元素有类、接口、枚举类型;方法
@Retention(RetentionPolicy.RUNTIME) //运行时可用反射调用
@Inherited //子类可以继承父类的注解
@Documented //生成doc文档时显示该注解
public @interface TargetAnnotationDemo {
 String value() default "hello";
 String value1();
}

第二步,写测试用例:

@TargetAnnotationDemo(value1 = "good")
public class TargetTest {
 @TargetAnnotationDemo(value1 = "good")
 public int add(int a, int b) {
  return a + b;
 }
}

/**

*子类,继承自TargetTest ,同时继承父类的TargetAnnotationDemo

*@author xiaoyun 2013-07-21

 

*/
class TargetTestChild extends TargetTest {
 @Override
 public int add(int a, int b) {
  // TODO Auto-generated method stub
  return super.add(a, b);
 }
}

第三步:

写测试类,TestTarget.java

import java.lang.annotation.Annotation;

public class TestTarget {
 public static void main(String[] args) {
  //实例化父类
  TargetTest parent = new TargetTest();
  //实例化子类
  TargetTestChild child = new TargetTestChild();
  //获取父类的类型
  Class cls = TargetTest.class;
  //获取子类的类型
  Class childCls = TargetTestChild.class;
  //获取父类的注解
  Annotation[] pAnnotations = cls.getAnnotations();
  if (pAnnotations.length > 0) {
   System.out.println("父类的注解:");
   for (Annotation annotation : pAnnotations) {
    System.out.println(annotation.annotationType().getName());   
   }
  }
  //获取子类的注解
  Annotation[] cAnnotations = childCls.getAnnotations();
  if (cAnnotations.length > 0) {
   System.out.println("子类的注解:");
   for (Annotation annotation : cAnnotations) {
    System.out.println(annotation.annotationType().getName());
   }
  }
 }
}

  该例子主要用到了java.lang.annotation.Annotation中的所有注解类型。对于Retention,Target,Inherited和Documented这是个注解类型,需要重点掌握前三个,第四个很少用到。

   这上面的两个例子都能正常运行,我的环境依然是,JDK1.6。对于生成doc文档的问题,你也可以通过javadoc命令来生成,但是如果你的开发工具时myeclipse8.6的话,可以通过project->Generate Javadoc来生成doc文档,通过去掉和加上@Documented注解类型来观察在文档中是否有对应的说明(当然去掉或加上后需要重新生成下)。

   这次先写到这里,关于注解在程序和框架中的应用案例,后面等我学习后会进行更新和发表,谢谢各位同行关注。

    欢迎各位同行和前辈们提出问题,对程序或者我组织的语言进行批评指导。

 

 

 

分享到:
评论

相关推荐

    java 自定义注解验证

    Java 自定义注解验证是Java开发中的一个重要特性,它允许开发者创建自己的元数据,以便在编译时或运行时对代码进行验证和处理。自定义注解为代码提供了额外的信息,使得程序更具可读性、可维护性和灵活性。在本案例...

    java自定义注解接口限流demo

    java自定义注解接口限流demo; java自定义注解接口限流demo; java自定义注解接口限流demo; java自定义注解接口限流demo; java自定义注解接口限流demo; java自定义注解接口限流demo; java自定义注解接口限流demo...

    Java自定义注解实例

    Java自定义注解是Java编程语言中的一个重要特性,它允许程序员在...自定义注解的灵活性和广泛用途使得它们成为现代Java开发不可或缺的一部分。在实际项目中,理解并熟练运用自定义注解能有效提高代码质量和可维护性。

    Java自定义注解使用反射获取字段注解

    Java自定义注解是Java语言中的一个重要特性,它允许我们创建自己的元数据,为代码提供额外的信息。在Java中,注解(Annotation)主要用于编译器检查、代码生成、运行时处理等方面。本文将深入探讨如何通过反射机制来...

    java自定义注解实践

    "java自定义注解实践" Java 自定义注解实践是 Java 语言中的一项重要特性,它可以使开发者自定义注解,以满足不同的需求。在本文中,我们将详细介绍 Java 自定义注解的概念、特点、实现方式及实践应用。 概念 ----...

    自定义注解实现伪动态传参的小demo

    自定义注解是扩展Java功能的强大工具,可以用于实现各种目的,如代码生成、编译时检查、运行时处理等。在这个“自定义注解实现伪动态传参的小demo”中,我们将探讨如何创建一个自定义注解,以允许在注解中传递类似于...

    java自定义注解和通过反射获取注解

    Java自定义注解和通过反射获取注解是Java编程中重要的高级特性,它们极大地增强了代码的可读性和可维护性。注解(Annotation)是一种元数据,提供了在编译时和运行时对代码进行标记的方法,而反射(Reflection)则是...

    java自定义注解实现由类自动生成表

    在本案例中,我们将探讨如何利用自定义注解实现在Java类定义后自动创建对应的数据库表,以适应SQL Server和Oracle这样的关系型数据库。 首先,我们需要理解自定义注解的基本结构。在Java中,你可以通过`@interface`...

    java 自定义注解例子

    总的来说,Java的自定义注解为我们提供了强大的元数据功能,能够灵活地扩展代码的行为和语义。通过自定义注解,我们可以更优雅地实现代码的解耦,增加代码的可读性和可维护性。在自动售卖机的例子中,我们展示了如何...

    Java自定义注解与spring BeanPostProcessor详解

    Java自定义注解和Spring的BeanPostProcessor是Java企业级开发中的两个重要概念,它们在构建灵活、可扩展的应用程序中发挥着关键作用。本文将深入探讨这两个话题,并结合源码分析,帮助开发者更好地理解和应用。 ...

    java自定义注解

    Java自定义注解是Java平台提供的一种元编程机制,它...通过自定义注解和处理器,开发者可以扩展Java语言,实现特定于应用的需求。在实际开发中,合理使用自定义注解可以提高代码的灵活性和可维护性,同时降低复杂性。

    实现生成自定义注解的实体类

    在Java编程语言中,自定义注解是一种强大的工具,它允许开发者创建自己的元数据,以提供额外的信息或规范代码的特定行为。自定义注解可以应用于类、接口、方法、变量等不同层级,使得代码更加模块化,易于理解和维护...

    spring aop 自定义注解保存操作日志到mysql数据库 源码

    3、对spring aop认识模糊的,不清楚如何实现Java 自定义注解的 4、想看spring aop 注解实现记录系统日志并入库等 二、能学到什么 1、收获可用源码 2、能够清楚的知道如何用spring aop实现自定义注解以及注解的逻辑...

    excel导入动态校验,自定义注解动态校验

    在实际项目中,这一功能常与Java的Spring框架结合,利用其提供的`@Validated`注解和`Validator`接口。此外,还可以利用Apache POI库来读取和操作Excel文件,以及Hibernate Validator库来处理自定义注解的校验逻辑。 ...

    java 自定义注解的实例详解

    Java 自定义注解的实例详解 Java 自定义注解是 Java 语言中的一种重要特性,它可以用于创建文档,跟踪代码中的依赖性,并且可以执行编译时期...通过掌握 Java 自定义注解,可以让开发者更好地控制和管理自己的代码。

    自定义注解实现拦截sql.rar

    以上就是利用自定义注解实现SQL拦截的基本原理和步骤,这个技术在处理复杂业务逻辑或者权限控制时非常有用,但同时也需要注意其潜在的风险和挑战。在实际项目中,应根据需求和项目规模合理使用。

    java 自定义注解

    以上就是关于Java自定义注解的基本概念、定义和使用方法。通过自定义注解,开发者可以更灵活地扩展Java语言的功能,实现更复杂的编程模式。在实际项目中,自定义注解常用于框架扩展、代码生成、验证规则设定等多种...

    Java自定义注解md,学习代码

    总之,这个压缩包的内容涵盖了Java自定义注解的基础知识,以及与Java Web相关的Tomcat服务器、用户会话管理等内容,对于理解和实践Java后端开发非常有帮助。通过深入学习这些材料,可以提高对Java编程和Web应用开发...

    java 元注解+拦截器实现自定义注解.rar

    java 元注解+拦截器实现自定义注解 @CmwAutoWired:自定义依赖注入 注意:注入的接口和实现类需要在同一包名下,注解的是类则无限制 @FieldAnnotation:自定义属性注解 @MethodAnnotation:自定义方法注解 @...

Global site tag (gtag.js) - Google Analytics