java6常用annotation_JAVA基础知识之Annotation

基本Annotation

Annotation必须使用工具(APT, Annotation tool)才能处理,Annotation可以在编译,类加载,运行时被读取,并执行相应处理。

下面介绍一些常用Annotation.

@Override

强制一个子类必须覆盖父类的方法,这样如果在子类中将需要覆盖的方法名写错了,在编译阶段就可以被发现

@Deprecated

标记某个类,方法等已经过时,编译时会有警告

@SuppressWarnings

将会取消编译器的警告。将对程序元素及下面所有子元素起作用。

用法举例,

1 packageAnnotation;2

3 importjava.util.ArrayList;4 importjava.util.List;5

6

7 public classSuppressWarningsTest {8 @SuppressWarnings("unchecked")9 public static voidmain(String[] args) {10 @SuppressWarnings("rawtypes")11 List list = newArrayList();12 list.add("aa");13 }14 }

@SafeVarargs

Java7 堆污染 警告

把一个不带泛型的变量赋值给带泛型的变量时,往往会发生 堆污染,例如下面的情况

1 List list = new ArrayList();2 //添加元素时引发unchecked异常

3 list.add(20);4 //下面的代码将引起“未经检查的转换”警告,编译、运行时候正常

5 List ls =list;6 //但是访问ls里的元素就会引起运行时异常

7 System.out.priintln(ls.get(0));

对于形参个数可变的方法,如果形参又是泛型,就更容易引起 堆污染,例如工具类

1 public classErrorUtils2 {3 public static void faultyMethod(List...listStrArray)4 {5 ...6 List[] listArray =listStrArray;7 ...8 }9 }

JAVA6以前,编译器在编译faultyMethod()方法时并不会发出警告,但是在使用这个方法的时候却发出警告:ClassCastException,

在JAVA7开始,编译器在编译ErrorUtils的时候就发出警告,可见JAVA7更严谨。

但是在某些情况下,开发者并不希望看到这种警告,于是可以用三种方法屏蔽,

@SafeVarargs , JAVA7推荐的方式,专门用来屏蔽 堆污染 警告

@SuppressWarnings("unchecked"),取消所有警告

@编译时使用-Xlint:varargs选项,不常用。

@FunctionalInterface

函数式接口限定,

JAVA 8中规定,如果接口中只有一个抽象方法(可以用多个其他方法),该接口就是函数式接口。

而@FunctionalInterface就是做这种编译检查的,如果在一个抽象接口中有两个以上抽象方法,就不再是函数式接口,编译器就会报错。

JDK的元Annotation

除了java.lang下的5个基本的Annotation之外,JDK还在java.lang.annotation下提供了6个Meta Annotation (元 Annotation). @Repeatable用来专门定义java8的重复注解。 其他的几个Annotation(@Retention, @Target, @Documented, @Inherited)则用来修饰其他的Annotation定义。

@Retention

用来修饰别的Annotation, 指定被修饰的Annotation的作用范围候(java文件中,还是class文件中,还是运行时)。

@Retention的使用格式为  @Retention(value=xxxx),也可以简化为@Retention(xxxx),当注解的成员变量只有"value"时就可以简写。

value可以有以下三中取值

RetentionPolicy.SOURCE: 仅在源码中可见,被修饰的Annotation只保留在java源码中,编译时直接丢弃。

RetentionPolicy.CLASS:保留在CLASS文件中,java程序运行时候不会读取。  这是默认值。

RetentionPolicy.RUNTIME,在运行时可见,也是记录在CLASS文件中,但是在运行的时候JVM还会从被修饰的Annotation中提取信息,程序也可以通过反射获取Annotation中的信息。

用法举例,

1 //下面被@Retention修饰的注解Testable将会保留到运行时

3 @Retention(value=RetentionPolicy.RUNTIME)

5 //上面一行也可以简写为

7 //@Retention(RetentionPolicy.RUNTIME)

8 public @interface Testable{}

@Target

也是用来修饰别的Annotation. 用于指定被修饰的Annotation只会对哪些程序元素(构造器,成员变量,成员方法等)起作用。value的取值如下,

ElementType.ANNOTATION_TYPE:指定该策略的annotation只能用来修饰Annotation

ElementType.CONSTRUCTOR:只能修饰构造器

//以下value取值可顾名思义

ElementType.FIELD

ElementType.LOCAL_VARIABLE

ElementType.METHOD

ElementType.PACKAGE

ElementType.PARAMETER

ElementType.TYPE:可修饰类,接口(包括注解类型)或枚举定义。

用法举例

1 @Target(ElementType.FIELD)2 //只能修饰成员变量

3 public @interface ActionListenerFor{}

@Documented

用来修饰别的annotation. 被修饰的annotation也会被javadoc提取

例如下面的用法,

1 @Retention(RetentionPolicy.RUNTIME)2 @Target(ElementType.METHOD)3 //定义Testable Annotation会被javadoc工具提取

4 @Documented5 public @interface Testable {}

在具体类中使用

1 public classMyTest2 {3 //@Testable也会被javadoc提取

4 @Testable5 public voidinfo()6 {7 ...8 }9 }

@Inherited

用来修饰其他annotion, 被修饰的annotation具有继承性。例如下面。

定义可继承的annotation: Inheritable

1 @Target(ElementType.TYPE)2 @Retention(RetentionPolicy.RUNTIME)3 @Inherited4 public @interface Inheritable {}

在基类上使用Inheritable,

1 //使用@Inheritable修饰的Base类

2 @Inheritable3 class Base {}

Base的子类中,即使没有显示使用Inheritable Annotation, 但会从父类继承,

1 //使用@Inheritable修饰的Base类

2 @Inheritable3 classBase {}

4 public class InheritableTest extends Base {}

自定义的Annotation

除了java.lang下的4个基本annotation,我们也可以自定义annotation.

自定义annotation

根据annotation是否可以包含成员变量,可以把annotation分为如下两类,即

标记Annotation:无成员变量,只利用自身是否存在来提供信息,例如@Override

元数据Annotation:包含成员变量,接收更多元数据。

定义一个annotation的方式与定义接口非常相似(继承自Annotation接口),以@inteface开头,可以有成员变量(及默认值),比如下面这样,

1 //自定义一个annotatio,包含两个成员变量,而且有默认值

2 public @interfaceMyTag3 {4   String name() default "xiao ming"

5   int age() default 2

6 }

下面是使用我们自定义的annotation

1 public classTest2 {3 @MyTag(name="xx", age=6)4 public voidinfo()5 {6 ...7 }8 ...9 }

提取Annotation信息

Annotation不会自己生效,而是需要写专门的程序来提取这些信息。从Java5开始,java.lang.reflect提供的反射API增加了运行时读取Annotation的能力,

当然只有将Annotation定义成@Retention(RetentionPolicy.RUNTIME)修饰,该Annotation才会在运行时可见。

Java5在java.lang.reflect下增加了AnnotatedElement接口,代表程序中可以接受注解的程序元素,主要实现类有Class, Constructor, Field, Method, Package等。AnnotatedElement是所有程序元素(Class, Constructor, Field, Method等)的父接口,所以当程序通过反射获取了某个类的AnnotatedElement对象(如Class, Constructor, Field, Method等)之后,就可以用下面方法访问Annotation的信息。

A getAnnotation(Class annotationClass) , 返回程序元素上指定类型的annotation

A getDeclaredAnnotation(Class annotationClass) , JDK8新增。 获取直接修饰程序元素的指定类型的annotation

Annotation[] getAnnotations(): 返回程序元素上的所有注解

Annotation[] getDeclaredAnnotations(); 返回直接修饰该程序元素的所有Annotation

boolean isAnnotationPresent(Class extends Annotation) annotationClass. 元素上是否存在指定类型的annotation

A[] getAnnotationByType(Class annotationClass , JDK8中允许重复注解,获取修饰该程序元素指定类型的多个annotation

A[] getDeclaredAnnotationByType(Class annotationClass , JDK8中允许重复注解,获取直接修饰该程序元素指定类型的多个annotation

下面举例,

1 //获取Test类的info方法的所有注解

2 Annotation[] aArray = Class.forName("Test").getMethod("info").getAnnotations();3 //遍历

4 for(Annotation an : aArray)5 {6 System.out.println(an);7

8 //如果要获取某个注解里的元数据,则可以将注解强制类型转换成所需注解类型,9 //然后通过注解对象的抽象方法来访问这些元数据10 //如果tag注解是MyTag1类型

11 if (tag instanceofMyTag1) {12 System.out.println("Tag is : "+tag);13 //强制转换

14 System.out.println("tag.name(): "+((MyTag1)tag).method1());15 System.out.println("tag.name(): "+((MyTag1)tag).method2());16 }17 //如果tag注解是MyTag2类型

18 if (tag instanceofMyTag1) {19 System.out.println("Tag is : "+tag);20 //强制转换

21 System.out.println("tag.name(): "+((MyTag2)tag).method1());22 System.out.println("tag.name(): "+((MyTag2)tag).method2());23 }24 }

下面这个例子,模拟JUnit的@Test注解,即只有在方法上加了@Test注解之后,JUnit才会执行这个方法。

首先自定一个Testable注解, 要@Retention来限定注解在程序运行时也有效,

1 packageann;2

3 importjava.lang.annotation.ElementType;4 importjava.lang.annotation.Retention;5 importjava.lang.annotation.RetentionPolicy;6 importjava.lang.annotation.Target;7

8 //自定义一个注解Testable,使用JDK的两个元注解来修饰他它。Retention设置注解保留时间到运行时,Target设置注解只对方法起作用

9 @Retention(value=RetentionPolicy.RUNTIME)10 @Target(ElementType.METHOD)11 public @interfaceTestable{12

13 }

写一个测试目标类MyTest,里面有8个方法,但是只有5个加了@Testable注解,

1 packageann;2

3 public classMyTest {4 //使用@Testable注释的方法指定该方法是可测试的

5 @Testable6 public static voidm1() {7

8 }9

10 public static voidm2() {11

12 }13

14 @Testable15 public static voidm3() {16 throw new IllegalArgumentException("参数错误!");17 }18

19 @Testable20 public static voidm4() {21

22 }23

24 @Testable25 public static voidm5() {26

27 }28

29 public static voidm6() {30

31 }32

33 @Testable34 public static voidm7() {35

36 }37

38 public static voidm8() {39

40 }41 }

如前面所说,注解并不会自动起作用,而是需要我们写额外的代码,通过反射去获取注解信息,并执行相应操作,

下面写一个专门的注解处理类,用来读取MyTest类中的Testable注解,从而控制MyTest类中哪些方法可以执行,

1 packageann;2

3 importjava.lang.reflect.Method;4

5 public classProcessorTest {6 public static void process(String clazz) throwsSecurityException, ClassNotFoundException {7 int passed = 0;8 int failed = 0;9 //遍历clazz对应类中的所有方法

10 for(Method m : Class.forName(clazz).getMethods() ) {11 //如果该方法使用了@Testable注解

12 if (m.isAnnotationPresent(Testable.class)) {13 try{14 //调用m方法

15 m.invoke(null);16 //测试成功,passed加1

17 passed++;18 } catch(Exception ex) {19 System.out.println("方法 "+m+" 运行失败,异常: "+ex.getCause());20 failed++;21 }22 }23 }24 //统计测试结果

25 System.out.println("共运行了: "+(passed + failed)+ " 个方法,其中成功了 "+passed+" 个,失败了 "+failed+" 个。");26 }27 }

再写一个测试类RunTests如下,我们执行RunTests类去测试MyTest类,实际是先通过上面的ProcessorTest类通过反射去读取MyTest类中的注解信息,决定哪些方法可以执行,就执行哪些方法,这个过程就跟JUnit一样。

1 packageann;2

3 public classRunTests {4 public static void main(String[] args) throwsSecurityException, ClassNotFoundException {5 ProcessorTest.process("ann.MyTest");6 }7 }

执行上面的测试类可以看到如下测试结果,

1 方法 public static voidann.MyTest.m3() 运行失败,异常: java.lang.IllegalArgumentException: 参数错误!2 共运行了: 5 个方法,其中成功了 4 个,失败了 1 个。

上面的例子只是通过反射来简单判断程序中是否有指定注解存在,下面的例子中,将读取注解的元数据信息,并根据信息做出相应操作。

下面通过注解来为Button绑定监听事件,这能简化编程,

首先自定义一个注解,将用来修饰Button,简单直观地说明Button将会使用哪个监听器

1 packageann;2

3 importjava.awt.event.ActionListener;4 importjava.lang.annotation.ElementType;5 importjava.lang.annotation.Retention;6 importjava.lang.annotation.RetentionPolicy;7 importjava.lang.annotation.Target;8

9 @Target(ElementType.FIELD)10 @Retention(value=RetentionPolicy.RUNTIME)11 public @interfaceActionListenerFor {12 //定义一个成员变量,用来设置元数据13 //该listener成员变量用于保存监听器实现类

14 Class extends ActionListener>listener();15 }

上面的自定义注解中,定义了一个成员变量 listener(),对应一个监听器ActionListener类的子类。在下面的Button上添加@ActionListenerFor注解,通过listener成员指定Button监听器的实现类。

1 packageann;2

3 importjavax.swing.JButton;4 importjavax.swing.JFrame;5 importjavax.swing.JPanel;6

7 public classAnnotationTest {8 private JFrame mainWin = new JFrame("使用注解绑定事件监听器");9 //使用Annotation为ok绑定事件监听器

10 @ActionListenerFor(listener=OkListener.class)11 private JButton ok = new JButton("确定");12 //使用Annotation为cancel绑定事件监听器

13 @ActionListenerFor(listener=CancelListener.class)14 private JButton cancel = new JButton("取消");15 public voidinit() {16 //初始化界面

17 JPanel jp = newJPanel();18 jp.add(ok);19 jp.add(cancel);20 mainWin.add(jp);21 ActionListenerInstaller.processAnnotations(this);22 mainWin.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);23 mainWin.pack();24 mainWin.setVisible(true);25 }26 public static voidmain(String[] args) {27 newAnnotationTest().init();28 }29 }

对应上面两个按钮,各写一个监听实现类,

1 packageann;2

3 importjava.awt.event.ActionEvent;4 importjava.awt.event.ActionListener;5

6 importjavax.swing.JOptionPane;7

8 public class OkListener implementsActionListener {9

10 @Override11 public voidactionPerformed(ActionEvent e) {12 //TODO Auto-generated method stub

13 JOptionPane.showMessageDialog(null, "单击了确认按钮");14 }15

16 }

1 packageann;2

3 importjava.awt.event.ActionEvent;4 importjava.awt.event.ActionListener;5

6 importjavax.swing.JOptionPane;7

8 public class CancelListener implementsActionListener{9

10 @Override11 public voidactionPerformed(ActionEvent e) {12 //TODO Auto-generated method stub

13 JOptionPane.showMessageDialog(null, "单击了取消按钮");14 }15

16 }

当然如果只是在上面AnnotationTest的注解中指定了Button的实现类,已然是无法实现Button和对应监听器的绑定的,我们需要专门写一个处理注解的类ActionListenerInstaller去处理,

1 packageann;2

3 importjava.awt.event.ActionListener;4 importjava.lang.reflect.Field;5

6 importjavax.swing.AbstractButton;7

8 public classActionListenerInstaller {9

10 public static voidprocessAnnotations(Object obj) {11 //TODO Auto-generated method stub

12 try{13 //获取obj对象的类

14 Class cl =obj.getClass();15 //获取指定obj对象的所有成员变量,并遍历每个成员变量

16 for(Field f : cl.getDeclaredFields()) {17 //将该成员变量设置成可自由访问

18 f.setAccessible(true);19 //获取该成员变量上ActionListenerFor类的 Annotaion

20 ActionListenerFor a = f.getAnnotation(ActionListenerFor.class);21 //获取成员变量f的值

22 Object fObj =f.get(obj);23 //如果f是AbstractButton的实例,且a不为null

24 if (a != null && fObj != null && fObj instanceofAbstractButton) {25 //获取a注解里的listener元数据(它是一个监听器)

26 Class extends ActionListener> listenerClazz = a.listener();27 //使用反射来创建listenr对象

28 ActionListener al =listenerClazz.newInstance();29 AbstractButton ab =(AbstractButton)fObj;30 //为ab按钮添加事件监听器

31 ab.addActionListener(al);32 }33 }34 } catch(Exception e) {35 e.printStackTrace();36 }37 }38

39 }

上面程序通过Class extends ActionListener> listenerClazz = a.listener();就得到了AnnotationTest中通过注解描述的Button的监听实现类,OkListener和CancelListener。然后通过addActionListener()方法将Button和注解中对应的监听实现类进行了绑定。

这样,我们每次添加Button时,只需要一行注解,就轻松实现了事件监听器的绑定。

运行AnnotationTest,点击 确定 或者 取消 , 可以见到触发的相应事件得到了响应。程序执行效果如下,

9b3709d91fcf5c4405af17a557127a8e.png

重复注解

在JAVA8以前,如果需要在一个程序元素上添加同类型的重复注解,需要像下面这样,

1 @Results({@Result(name="failure", location="failed.jsp"), @Result(name="success", location="succ.jsp")})2 public Action FooAction{...}

而在JAVA8后,则可以直接添加同类型的多个注解,但是需要先添加@Repeatable注解,

首先定义一个FKTag注解,

1 @Retention(RetentionPolicy.RUNTIME)2

3 @Target(ElementType.TYPE4

5 public @interfaceFKTag {6

7   String name() default "Johnny";8

9   intage();10

11 }

还需要定义一个FKTags注解

1 @Retention(RetentionPolicy.RUNTIME)2

3 @Target(ElementType.TYPE4

5 public @interfaceFKTags {6

7 FKTag[] value();8

9 }

这样,可在定义@FKTag时,添加下面注解

1 @Repeatable(FKTags.class)

最后,就可以在程序元素上重复使用FKTag注解了

1 @FKTag(age=5)2

3 @FKTag(name="xiaoming", age=9}

实际上,JAVA8的这种写法只是以前版本的简写,其内部实现已然是数组形式的。

JAVA8中的type Annotation

JAVA8以前,Annotation只能用在程序元素声明语句上,JAVA8开始引入了Type Annotation,可以用在任何程序元素地方(声明,类型转换时,初始化对象时等等, 以实现对程序任何地方进行干涉处理的目的。让程序中编译时进行更严格的检查,增加程序的健壮性。

JAVA8以前我们通过Target指定Annotation对什么程序元素有效(类,成员变量,成员方法等),在JAVA8开始,新增Target参数ElementType.TYPE_USE使得Annotation可以用在任何地方。

例如我们先定义一个Type Annotation

1 @Target(ElementType.TYPE_USE)2 @interface NotNull{}

下面是简单用法,

1 public class TypeAnnotationTest implements@NotNull Serialiable2 {3 //方法形参中使用Type Annotation

4 public static void main(@NotNull String[] args) throws@NotNull FileNotFoundException5 {6 Object obj = "abcd.txt"

7 //强制类型转换时使用Type Annotation

8 String str =(@NotNull String)obj;9 //创建对象时使用Type Annotation

10 Object win = new @NotNull JFrame("测试");11 }12 //泛型中使用Type Annotation

13 public void foo(Listinfo(){}14 }

可以看到用了Type Annotation之后可以在编译时更方便更严格地进行检查,增强了程序的健壮性。

编译时处理Annotation

通过我们自己编写的注解处理类  APT (Annotation Processing Tool), 可以对源码中的Annotation进行检查并处理,还能针对Annotation信息添加进额外的信息,这个机制可以大大简化我们的编程。

例如在Hibernate中,每一个数据表class文件都会对应一个*.hbm.xml文件,这个xml文件就是通过APT根据java文件中的Annotation信息在编译过程中生成的。

通过javac -processor,我们可以在编译时指定一个注解处理器,实现编译期间的注解处理。注意,这个注解处理器需要先编译好,才能用做其他类的注解处理器。

指定的注解处理器,是需要继承AbstractProcessor类,并且实现process方法。

下面来演示Hibernate的关联的xml自动生成的实现过程,

首先我们自定义三个普通的注解,分别表示数据库表名,主键字段,属性字段

1 importjava.lang.annotation.Documented;2 importjava.lang.annotation.ElementType;3 importjava.lang.annotation.Retention;4 importjava.lang.annotation.RetentionPolicy;5 importjava.lang.annotation.Target;6

7 @Target(ElementType.TYPE)8 @Retention(RetentionPolicy.SOURCE)9 @Documented10 public @interfacePersistent {11 String table();12 }

1 importjava.lang.annotation.Documented;2 importjava.lang.annotation.ElementType;3 importjava.lang.annotation.Retention;4 importjava.lang.annotation.RetentionPolicy;5 importjava.lang.annotation.Target;6

7 @Target(ElementType.FIELD)8 @Retention(RetentionPolicy.SOURCE)9 @Documented10 public @interfaceId {11 String column();12 String type();13 String generator();14 }

1 importjava.lang.annotation.Documented;2 importjava.lang.annotation.ElementType;3 importjava.lang.annotation.Retention;4 importjava.lang.annotation.RetentionPolicy;5 importjava.lang.annotation.Target;6

7 @Target(ElementType.FIELD)8 @Retention(RetentionPolicy.SOURCE)9 @Documented10 public @interfaceProperty {11 String column();12 String type();13 }

我们在具体的JAVA类中使用上面三个注解,假设现在有一张数据库表person_inf, 我们为其建立一个实体类Person

1 @Persistent(table="person_inf")2 public classPerson {3 @Id(column="person_id", type="integer", generator="identity")4 private intid;5 @Property(column="person_name", type="string")6 privateString name;7 @Property(column="person_age", type="age")8 private intage;9

10 //无参构造

11 publicPerson() {}12

13 //有参构造

14 public Person(int id, String name, intage) {15 this.id =id;16 this.name =name;17 this.age =age;18 }19 }

上面的类中使用了三种注解,但是这些注解不会自动生效,需要我们为其专门写一个注解处理类(APT)HibernateAnnotationProcessor,

在注解处理类中,我们根据注解中对类变量的属性描述,生成一个Person.hbm.xml文件,

1 importjava.io.FileOutputStream;2 importjava.io.PrintStream;3 importjava.util.Set;4

5 importjavax.annotation.processing.AbstractProcessor;6 importjavax.annotation.processing.RoundEnvironment;7 importjavax.annotation.processing.SupportedAnnotationTypes;8 importjavax.annotation.processing.SupportedSourceVersion;9 importjavax.lang.model.SourceVersion;10 importjavax.lang.model.element.Element;11 importjavax.lang.model.element.ElementKind;12 importjavax.lang.model.element.Name;13 importjavax.lang.model.element.TypeElement;14

15 @SupportedSourceVersion(SourceVersion.RELEASE_7)16 @SupportedAnnotationTypes({"Persistent", "Id", "Property"} )17 public class HibernateAnnotationProcessor extendsAbstractProcessor {18

19 @Override20 public boolean process(Set extends TypeElement>annotations,21 RoundEnvironment roundEnv) {22 PrintStream ps = null;23 try{24 for (Element t : roundEnv.getElementsAnnotatedWith(Persistent.class)) {25 //获取类名

26 Name clazzName =t.getSimpleName();27 //获取注解

28 Persistent per = t.getAnnotation(Persistent.class);29 ps =new PrintStream(new FileOutputStream(clazzName + ".hbm.xml"));30 ps.println("<?xml version=\"1.0\"?>");31 ps.println(""-//Hibernate/Hibernate "+"Mapping DTD 3.0//EN\"");33 ps.println(" \"http://www.hibernate.org/dtd/" + "hibernate-mapping-3.0.dtd\">");34 ps.println("");35 ps.println("

37 ps.println("\" table=\"" + per.table() + "\">");38 for(Element f : t.getEnclosedElements()) {39 //只处理成员变量上的Annotation

40 if (f.getKind() ==ElementKind.FIELD) {41 Id id = f.getAnnotation(Id.class);42 if (id != null) {43 ps.println("

44 +f.getSimpleName()45 + "\" + column=\"" +id.column()46 + "\" + type=\"" +id.type()47 + "\">");48 ps.println("

49 + id.generator() + "\"/>");50 ps.println("

");51 }52 //获取成员变量前的Property

53 Property p = f.getAnnotation(Property.class);54 if (p != null) {55 ps.println("

56 +f.getSimpleName()57 +"\" column=\"" +p.column()58 +"\" type=\"" +p.type()59 +"\"/>");60 }61 }62 }63 ps.println("

");64 ps.println("");65 }66 } catch(Exception ex) {67 ex.printStackTrace();68 } finally{69 if (ps != null) {70 try{71 ps.close();72 }catch(Exception ex) {73 ex.printStackTrace();74 }75 }76 }77

78 return true;79 }80

81 }

执行下面两行编译语句,

1 javac HibernateAnnotationProcessor.java2 javac -processor HibernateAnnotationProcessor Person.java

之后会发现生成了一个Person.hbm.xml文件如下,

1 <?xml version="1.0"?>

2 "-//Hibernate/Hibernate Mapping DTD 3.0//EN"4 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

5

6

8

9

10

11

12

13

14

通过以上 javac -processer的方法,就实现了编译期间使用处理器对类的注解进行处理的目的,上面生成的xml文件就可以供Hibernate后面使用。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值