注解是代码的附属信息,它遵循一个原则:注解不能直接干涉程序代码的运行,无论增加或者删除注解,代码都能够正常运行。java语言解释器会忽略掉这些注解,而由第三方工具负责对注解进行处理。第三方工具可以利用代码中的注解间接的控制程序代码的运行,他们通过java的反射机制读取注解的信息,并根据这些信息更改目标程序的逻辑。
注解定义类:
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Author: Leo Sun * Blog: http://fuxinci.com/ * Date: 3/27/13 */ @Retention(RetentionPolicy.RUNTIME) // 声明注解的保留期限 @Target(ElementType.METHOD) // 声明可以使用该注解的目标类型 public @interface NeedTest { // 定义注解 boolean value() default true; // 声明注解成员,1.成员无入参无抛出异常的方式声明,2.可以通过default为成员指定一个默认值,3.成员类型受限,合法类型包括原始类型和包装类
// 如果只有一个属性,那么必须是value }
Retention,在java.lang.annotation.RetentionPolicy中定义
SOURCE:注册信息仅保留在目标代码的源文件中,对相应的字节码文件将不保留。
CLASS:注解信息将进入目标类代码的字节码文件中,但是类加载其加载字节码文件时不会将注解加载到JVM中,即运行期无法获得注解信息。
RUNTIME:注解信息在目标类加载到JVM后依然保留,在运行期可以通过反射机制读取类中注解的内容。
Target,在java.lang.annotation.ElementType中进行定义
TYPE:类,接口,注解类,Enum声明处
FIELD:类成员变量或常量声明处
METHOD:方法声明处
PARAMETER:参数声明处
CONSTRUCTOR:构造函数声明处
LOCAL_VARIABLE:局部变量声明处
ANNOTATION_TYPE:注解类声明处
PACKAGE:包声明处
使用注解
/** * Author: Leo Sun * Blog: http://fuxinci.com/ * Date: 3/27/13 */ public class ForumService { @NeedTest(true) public void deleteForum(int forumId) { System.out.println("Delete forum :" + forumId); } @NeedTest(false) public void deleteTopic(int topicId) { System.out.println("Delete topic :" + topicId); } }
测试代码
import java.lang.reflect.Method; /** * Author: Leo Sun * Blog: http://fuxinci.com/ * Date: 3/27/13 */ public class TestTool { public static void main(String[] args) { Class clazz = ForumService.class; Method[] methods = clazz.getDeclaredMethods(); System.out.println(methods.length); for (Method method : methods) { NeedTest nt = method.getAnnotation(NeedTest.class); if (nt != null) { if (nt.value()) { System.out.println(method.getName() + " Need Test..."); } else { System.out.println(method.getName() + " Need Not Test..."); } } } } }