Annotation (Annotation) source code parsing-simple implementation (Hibernate, EJB, JPA)

Source: Internet
Author: User

Annotations provide a structured and new way of checking types, so that programmers can add metadata to the code without causing code clutter and difficulty in understanding. For example, @ Override indicates the inheritance class or interface method overloading.

 

Annotation stores all information at the actual source code level, rather than comments.

 

Column implementation and application cases in hibernate, EJB, and JPA:

 

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}) // specifies the element type, method level, and domain (attribute) level @ retention (retentionpolicy. runtime) // The retention policy is at the runtime level. Annotations can get public @ interface column {string name () Default "through reflection at runtime ""; // The default keyword can be set for the name method. The default value is 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());  } }}

The console displays the following results:

Name 20 true
Description 100 false

Simple application source code analysis:

1. Field [] fields = UseCase. class. getDeclaredFields ();

Through reflection, UseCase. class. getDeclaredFields () obtains the declared domain of the class Object of the UseCase class.

AnnotationParser. getDeclaredFields (...) Method

Public Field [] getDeclaredFields () throws SecurityException {checkMemberAccess (Member. DECLARED, ClassLoader. getCallerClassLoader (); // check if the class member accesses return copyFields (privateGetDeclaredFields (false); // return a copy of the private object to obtain the declared domain}

2. for (Field field: fields) {...} // traverse the fields Array

3. Column column = field. getAnnotation (Column. class); // obtain the field-level Annotation @ Column

AnnotationParser. getAnnotation (...) Method

Public <T extends Annotation> T getAnnotation (Class <T> annotationClass) {if (annotationClass = null) throw new NullPointerException (); return (T) declaredAnnotations (). get (annotationClass); // call the declared annotation method to obtain the annotation of the specified @ Column type}

Annotationparser. declaredannotations (...) Method

Private synchronized Map <class, annotation> declaredannotations () {If (declaredannotations = NULL) {declaredannotations = annotationparser. parseannotations (annotations, Sun. misc. sharedsecrets. getjavalangaccess (). getconstantpool (getdeclaringclass (), getdeclaringclass (); // annotation parsing. Annotations are byte [], Sun. misc. sharedsecrets. getjavalangaccess (). // getconstantpool (getdeclaringclass () injection getdeclaringclass () is usecase. class Object to obtain the constant pool accessed by the Java language} return declaredannotations ;}

Annotationparser. parseannotations (...) Method

Public static Map <class, annotation> parseannotations (byte [] paramarrayofbyte, constantpool paramconstantpool, class paramclass) {// {code ...} return parseannotations2 (paramarrayofbyte, paramconstantpool, paramclass); // call the parseannotations2 method // {code ...}}

AnnotationParser. parseAnnotations2 (...) Method

Private Static Map <class, annotation> parseannotations2 (byte [] paramarrayofbyte, constantpool paramconstantpool, class paramclass) {linkedhashmap local1_hashmap = new linkedhashmap (); // declare the hashmap bytebuffer localbytebuffer = bytebuffer of a linked list. wrap (paramarrayofbyte); // load the byte array into bytebuffer int I = localbytebuffer. getshort () & 0 xFFFF; // obtain the localbytebuffer size for (Int J = 0; j <I ;++ J) {annotation L Ocalannotation = parseannotation (localbytebuffer, paramconstantpool, paramclass, false); // parse annotation if (localannotation! = NULL) {class localclass = localannotation. annotationtype (); annotationtype localannotationtype = annotationtype. getinstance (localclass); // annotationtype obtain annotation type if (localannotationtype. Retention ()! = Retentionpolicy. runtime) | (local1_hashmap. put (localclass, localannotation) = NULL) continue; // specifies that the retention policy of annotation @ column must be at the runtime level, add the annotation type and annotation object to localjavashashmap. Throw new annotationformaterror ("Duplicate annotation for class:" + localclass + ":" + localannotation);} return local#hashmap ;}

AnnotationParser. parseAnnotation (...) Method

Private static Annotation parseAnnotation (ByteBuffer paramByteBuffer, ConstantPool paramConstantPool, Class paramClass, boolean paramBoolean) {int I = paramByteBuffer. getShort () & 0 xFFFF; Class localClass1 = null; String str1 = paramConstantPool. getUTF8At (I); // obtain Column localClass1 = parseSig (str1, paramClass); // obtain the @ Column Interface class Object through UseCase and Column parsing // {code ...} annotationType localAnnotationType = AnnotationType. getInstance (localClass1); // obtain the annotation type @ Column Map localMap = localAnnotationType. memberTypes (); // obtain the annotation @ Column member type LinkedHashMap local1_hashmap = new LinkedHashMap (localAnnotationType. memberDefaults (); // Add the default value of the member type of @ Column to local1_hashmap int j = paramByteBuffer. getShort () & 0 xFFFF; for (int k = 0; k <j; ++ k) {int l = paramByteBuffer. getShort () & 0 xFFFF; String str2 = paramConstantPool. getUTF8At (l); // obtain the name of the member type, such as name Class localClass2 = (Class) localMap. get (str2); Object localObject = parseMemberValue (localClass2, paramByteBuffer, paramConstantPool, paramClass); // obtain the value of a member, for example, "name" localLinkedHashMap. put (str2, localObject); // {code ...}} return annotationForMap (localClass1, localLinkedHashMap); // @ Column. class Object and localLinkedHashMap create @ Column object}

AnnotationParser. annotationForMap (...) Method

Public static Annotation annotationForMap (Class paramClass, Map <String, Object> paramMap) {return (Annotation) Proxy. newProxyInstance (paramClass. getClassLoader (), new Class [] {paramClass}, new AnnotationInvocationHandler (paramClass, paramMap); // create @ Column object}

After reading the source code implementation, the Java reflection mechanism and proxy class are used to create annotation interface objects for the specified domain (method or class) and their attributes.

In fact, in Java, these things seem very difficult to implement (for 'yourself '), but you can look at the source code and look at his design philosophy, you may have some insights and learning to understand the implementation of Java APIs. This requires patience and patience.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.