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

     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;
	}
	
	@HelloWorld
	public String print(String chineseName,String enlishName) {
		System.out.println(chineseName+","+enlishName);
		return chineseName+","+enlishName;
	}
	@HelloWorld
	@Override
	public 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:jim
before invoke
zhangsan,lisi
after invoke

方法 toString():   --------------------------------
hw.chineseName:杰姆
hw.value:jim
before invoke
王五,wangwu
after invoke

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

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


猜你喜欢

转载自blog.csdn.net/z0157/article/details/47862807