注解提供了一种结构化的,并且具有类型检查能力的新途径,从而使程序员能够为代码加入元数据,而不会导致代码杂乱且难以理解。如:@Override 说明继承类或实现接口方法重载。
注解是在实际的源代码级别保存所有的信息,而不是某种注释性的文字。
在Hibernate,EJB,JPA中Column实现和应用程序案例:
Column.java
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.METHOD,ElementType.FIELD}) // 目标可以指定的元素类型方法级别和域(属性)级别 @Retention(RetentionPolicy.RUNTIME) // 保留方针为运行时级别,注解可以在运行时通过反射获得 public @interface Column { String name() default ""; // default 关键字可以为name方法设置默认值 boolean unique() default false; boolean nullable() default true; boolean insertable() default true; boolean updateable() default true; String columnDefinition() default ""; String secondaryTable() default ""; int length() default 255; int precision() default 0; int scale() default 0; }
UseCase.java
import java.lang.reflect.Field; public class UseCase { @Column(name = "name", length = 20, unique = true) private String name; @Column(name = "description", length = 100) private String description; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getDescription() { return description; } public void setDescription(String description) { this.description = description; } public static void main(String[] args) { Field[] fields = UseCase.class.getDeclaredFields(); for (Field field : fields) { Column column = field.getAnnotation(Column.class); System.out.println(column.name() + " " + column.length() + " " + column.unique()); } } }
控制台显示的结果为:
name 20 true
description 100 false
应用程序简单应用源码解析:
1. Field[] fields = UseCase.class.getDeclaredFields();
通过反射,UseCase.class.getDeclaredFields()获得UseCase类的class对象的声明的域。
AnnotationParser.getDeclaredFields(...)方法
public Field[] getDeclaredFields() throws SecurityException { checkMemberAccess(Member.DECLARED, ClassLoader.getCallerClassLoader()); // 检查类成员访问 return copyFields(privateGetDeclaredFields(false)); // 返回一份私有获得声明域的拷贝 }
2. for (Field field : fields) {...} // 遍历fields数组
3. Column column = field.getAnnotation(Column.class); // 获得域级别的注解Annotation @Column
AnnotationParser.getAnnotation(...)方法
public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { if (annotationClass == null) throw new NullPointerException(); return (T) declaredAnnotations().get(annotationClass);// 调用声明的注解方法,获得指定@Column类型的注解 }
AnnotationParser.declaredAnnotations(...)方法
private synchronized Map<Class, Annotation> declaredAnnotations() { if (declaredAnnotations == null) { declaredAnnotations = AnnotationParser.parseAnnotations( annotations, sun.misc.SharedSecrets.getJavaLangAccess(). getConstantPool(getDeclaringClass()), getDeclaringClass()); // 注解解析,annotations为byte[],sun.misc.SharedSecrets.getJavaLangAccess(). // getConstantPool(getDeclaringClass()) 注入getDeclaringClass())即UseCase.class对象,获得Java语言访问的常量池 } return declaredAnnotations; }
AnnotationParser.parseAnnotations(...)方法
public static Map<Class, Annotation> parseAnnotations(byte[] paramArrayOfByte, ConstantPool paramConstantPool, Class paramClass)
{
// {code...}
return parseAnnotations2(paramArrayOfByte, paramConstantPool, paramClass);// 调用parseAnnotations2方法
// {code...}
}
AnnotationParser.parseAnnotations2(...)方法
private static Map<Class, Annotation> parseAnnotations2(byte[] paramArrayOfByte, ConstantPool paramConstantPool, Class paramClass) { LinkedHashMap localLinkedHashMap = new LinkedHashMap();// 声明一个链表的HashMap ByteBuffer localByteBuffer = ByteBuffer.wrap(paramArrayOfByte);// 将字节数组装入ByteBuffer中 int i = localByteBuffer.getShort() & 0xFFFF;// 获得localByteBuffer的大小 for (int j = 0; j < i; ++j) { Annotation localAnnotation = parseAnnotation(localByteBuffer, paramConstantPool, paramClass, false); //解析Annotation if (localAnnotation != null) { Class localClass = localAnnotation.annotationType(); AnnotationType localAnnotationType = AnnotationType.getInstance(localClass); // AnnotationType获得注解类型 if ((localAnnotationType.retention() != RetentionPolicy.RUNTIME) || (localLinkedHashMap.put(localClass, localAnnotation) == null)) continue; // 说明注解@Column的保留方针必须为RUNTIME级别,并将注解类型和注解对象放入localLinkedHashMap中 throw new AnnotationFormatError("Duplicate annotation for class: " + localClass + ": " + localAnnotation); } } return localLinkedHashMap; }
AnnotationParser.parseAnnotation(...)方法
private static Annotation parseAnnotation(ByteBuffer paramByteBuffer, ConstantPool paramConstantPool, Class paramClass, boolean paramBoolean) { int i = paramByteBuffer.getShort() & 0xFFFF; Class localClass1 = null; String str1 = paramConstantPool.getUTF8At(i);//获得Column localClass1 = parseSig(str1, paramClass);// 通过UseCase和Column解析得到@Column接口class对象 //{code...} AnnotationType localAnnotationType = AnnotationType.getInstance(localClass1);//获得注解类型@Column Map localMap = localAnnotationType.memberTypes();// 获得注解@Column的成员类型 LinkedHashMap localLinkedHashMap = new LinkedHashMap(localAnnotationType.memberDefaults()); //@Column的成员类型的默认值放入localLinkedHashMap int j = paramByteBuffer.getShort() & 0xFFFF; for (int k = 0; k < j; ++k) { int l = paramByteBuffer.getShort() & 0xFFFF; String str2 = paramConstantPool.getUTF8At(l);// 获得成员类型的名称如name Class localClass2 = (Class)localMap.get(str2); Object localObject = parseMemberValue(localClass2, paramByteBuffer, paramConstantPool, paramClass); //获得成员的值如name的值为"name" localLinkedHashMap.put(str2, localObject); //{code...} } return annotationForMap(localClass1, localLinkedHashMap); // 通过@Column.class对象和localLinkedHashMap创建@Column对象 }
AnnotationParser.annotationForMap(...)方法
public static Annotation annotationForMap(Class paramClass, Map<String, Object> paramMap) { return (Annotation)Proxy.newProxyInstance(paramClass.getClassLoader(), new Class[] { paramClass }, new AnnotationInvocationHandler(paramClass, paramMap)); // 创建@Column对象 }
看过源码实现之后,其实就是通过Java的反射机制和代理类来创建指定域(方法或者类)的注解接口对象以及他的属性。
发表评论
-
J2EE、J2SE、J2ME区别
2012-04-21 18:07 1332JAVA2平台是提供JAVA程序开发、运行环境的平台,JAVA ... -
[转载]JDK和JRE目录的文件结构
2012-04-21 17:12 1845[转载 ] 我们下 ... -
[转载]SDK、JDK、JRE和JVM的关系总结
2012-04-12 22:16 2026一、SDK、JDK、JRE和JVM的 ... -
Java注解
2012-04-11 02:02 1724可以先看看转载的三篇博客: Java注解--基础知识 ... -
[转载]Java注解--基础知识
2012-04-10 23:53 1478[转载 ] 一、什么是java 注 ... -
[转载]Java注解--原理
2012-04-10 23:34 1229[转载 ] 在开发Java ... -
集合初探--集合中的其它设计模式
2011-03-27 21:35 11741.集合中的工厂方法模式 ·工厂方法(FactoryMet ... -
集合初探--集合中的设计模式之Iterator模式
2011-03-27 21:35 12501. Iterator模式 ·标准定义:提供一种统一的方法顺 ... -
集合初探--Fail-Fast机制
2011-03-27 21:35 1162Fail-Fast机制 ·在系统发生错误后,立即作出响应,阻 ... -
集合初探--认识Set
2011-03-27 21:34 9761. HashSet ·基于HashMap实现的,Hash ... -
集合初探--认识Map
2011-03-27 21:34 10691. HashMap A)底层数据结构 ·HashMap ... -
集合初探--认识List
2011-03-27 21:34 13571. ArrayList A) 底层数据结构 ·本质是 ... -
集合初探--集合框架
2011-03-24 09:44 1090最近学习了java集合,将自己学习的笔记整理后发布到博客,本系 ...
相关推荐
JAVA设计模式--程序设计--反射--注解--泛型
java注解代码java注解代码java注解代码java注解代码java注解代码java注解代码java注解代码java注解代码java注解代码java注解代码java注解代码java注解代码java注解代码java注解代码java注解代码java注解代码java注解...
NULL 博文链接:https://2528.iteye.com/blog/1133871
Java 第二阶段建立编程思想 【枚举和注解】---- 代码 Java 第二阶段建立编程思想 【枚举和注解】---- 代码 Java 第二阶段建立编程思想 【枚举和注解】---- 代码 Java 第二阶段建立编程思想 【枚举和注解】---- 代码 ...
---注解---.xmind Java常用各种注解
spring注解 -----最简单的注解与自动装配例子
内容概要:通过带着读者编写Java基础语法测试代码,理解基础数据类型-注解-数组-inet-反射-oop-Java代码实现过程和测试代码 适合人群:初学java语法入门测试代码 能学到什么:①注解、数组、数据类型、inet、method...
十二长生歌诀注解-甲木长生口诀[文].pdf
Java-JDBC【之】实现ORM,结果集映射实体类(ResultSet、注解、反射) 1.ORM实现思路 2.@Table、@Column、标识实体类 2.1.创建注解 @Table、@Column 2.2.标识实体类 2.3.数据库表 3.结果集解析,注解加反射填充实体...
java注解解析知识要点 精简易懂
使用注解控制java事务, 类似spring处理,代码干净简洁
spring-demo10-注解-IOC.zip
spring-demo13-注解-@Value.zip
java注解和反射的个人学习笔记
5-java进阶-枚举与注解1
JAXB-XML注解-应用
Java注解实现
机器学习实战(第六章-支持向量机-所有代码与详细注解-python3.7) 机器学习实战(第六章-支持向量机-所有代码与详细注解-python3.7)
SimpleFramework的作者写的文档,和github上的不太一样
SpringMVC精品资源--教程源码-springboot部分SpringMVC常用的注解; SpringBoot