Java 注解的简单学习与应用 Annotation

来源:互联网 发布:qq mac版 编辑:程序博客网 时间:2024/05/16 19:04

     JPA学习之前我先学习了一下注解,在很多项目的框架的底层代码中,我们都会发现一些由架构师搭建框架的时候写的一些自定义的注解,什么是注解(Annotation)?Annotation是一种应用于类、方法、参数、变量、构造器及包声明中的特殊修饰符。按照百度百科上解释是“它是一种由JSR-175标准选择用来描述元数据的一种工具”;Annotations仅仅是元数据,和业务逻辑无关;Annotations仅仅提供它定义的属性(类/方法/包/域)的信息。Annotations的用户(同样是一些代码)来读取这些信息并实现必要的逻辑。

-----------------------------------------------------

J2SE5.0版本在 java.lang.annotation提供了四种元注解,专门注解其他的注解:
@Documented –注解是否将包含在JavaDoc中
@Retention –什么时候使用该注解
@Target? –注解用于什么地方
@Inherited – 是否允许子类继承该注解


详细大概介绍下:
1.@Documented–
  一个简单的Annotations标记注解,表示是否将注解信息添加在java文档中(可以被例如javadoc此类的工具文档化)。
2.@Retention– 
  定义该注解的生命周期。
3.RetentionPolicy.SOURCE – 
  在编译阶段丢弃。这些注解在编译结束之后就不再有任何意义,所以它们不会写入字节码。       @Override,@SuppressWarnings都属于这类注解。
4.RetentionPolicy.CLASS – 
  在类加载的时候丢弃。在字节码文件的处理中有用。注解默认使用这种方式。
5.RetentionPolicy.RUNTIME– 

  始终不会丢弃,运行期也保留该注解,因此可以使用反射机制读取该注解的信息。我们自定义的注解通常使用这种方式。
6.@Target – 

  表示该注解用于什么地方。如果不明确指出,该注解可以放在任何地方。以下是一些可用的参数。需要说明的是:属性的注解是兼容的,如果你想给7个属性都添加注解,仅仅排除一个属性,那么你需要在定义target包含所有的属性。
ElementType.TYPE:用于描述类、接口或enum声明
ElementType.FIELD:用于描述实例变量
ElementType.METHOD
ElementType.PARAMETER
ElementType.CONSTRUCTOR
ElementType.LOCAL_VARIABLE
ElementType.ANNOTATION_TYPE 另一个注释
ElementType.PACKAGE 用于记录java文件的package信息
7.@Inherited – 
  定义该注释和子类的关系:允许子类继承父类中的注解;
如果一个使用了@Inherited修饰的annotation类型被用于一个class,则这个annotation将被用于该class的子类。


下面我就写个简单的demo来介绍下:

package com.rong.zhu.jpa;import java.lang.annotation.Documented;import java.lang.annotation.Inherited;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;/** * @author zhurong * */@Documented@Retention(RetentionPolicy.RUNTIME)@Inherited //允许子类继承父类中的注解//@Target(ElementType.METHOD) 不用,就默认都可以用public @interface HelloWorld {public String chineseName() default "杰姆";public String enlishName() default "jim";}

package com.rong.zhu.jpa;/** * @author zhurong * */public class TestCase {@HelloWorld(chineseName="你好")private String chineseName;//注解中只有一个属性,可以直接命名为"value""enlishName=" 可以省略不写@HelloWorld(enlishName="nihao")private String enlishName;public TestCase(String chineseName,String enlishName) {this.chineseName = chineseName;this.enlishName = enlishName;}@HelloWorldpublic String print(String chineseName,String enlishName) {System.out.println(chineseName+","+enlishName);return chineseName+","+enlishName;}@HelloWorld@Overridepublic String toString() {System.out.println(this.chineseName+","+this.enlishName);return this.chineseName+","+this.enlishName;}}

package com.rong.zhu.jpa;import java.lang.reflect.Method;/** * @author zhurong * */public class ParseAnnotaion {public void parse(Object obj, String methodName,String chineseName,String EnlishName) {Method[] ms = obj.getClass().getMethods();for (Method m : ms) {if (m.isAnnotationPresent(HelloWorld.class)&& methodName.equals(m.getName())) {HelloWorld hw = m.getAnnotation(HelloWorld.class);System.out.println("hw.chineseName:"+hw.chineseName());System.out.println("hw.value:"+hw.enlishName());try{System.out.println("before invoke");if(chineseName=="" && EnlishName==""){m.invoke(obj,null);}else{m.invoke(obj,(Object)chineseName,(Object)EnlishName);}System.out.println("after invoke");}catch(Exception e){e.printStackTrace();}}}}}

package com.rong.zhu.jpa;/** * @author zhurong * */public class MainTest {public static void main(String[] args) {TestCase tc = new TestCase("王五","wangwu");ParseAnnotaion parseAnno = new ParseAnnotaion();System.out.print("方法  print():");System.out.println("   ------------------------------");parseAnno.parse(tc, "print", "zhangsan", "lisi");System.out.print("\n"+"方法 toString():");System.out.println("   --------------------------------");parseAnno.parse(tc, "toString", "", "");}}

运行结果:

方法  print():   ------------------------------hw.chineseName:杰姆hw.value:jimbefore invokezhangsan,lisiafter invoke方法 toString():   --------------------------------hw.chineseName:杰姆hw.value:jimbefore invoke王五,wangwuafter invoke

备注:在写这代码的过程中,我也遇到了一个bug,是关于发射的,这个请见我的另外一片文章:

《解析Java反射java.lang.IllegalArgumentException: wrong number of arguments》


0 0