Java annotation and framework secrets

Source: Internet
Author: User

When you use spring MVC or hibernate 3.0 or later versions, you may notice the convenience of Annotation. However, this often makes people think that annotation is really powerful, this is a close-to-error understanding. annotation is actually a document annotation method that helps us use it during compilation, runtime, and document generation, in fact, some annotation is basically similar to the annotation. Here we will talk about the principle of annotation, how to implement various functions on it, and what will happen to annotation during inheritance? Why?


First, in my personal understanding, annotation isClass, type, attribute, parameter, local variable, method, constructor, package, AnnotationAs described in the enumeration of elementtype, annotation relies on these elements and does not play any role in itself, parsing based on an external program causes this function. For example, during compilation, the compilation phase is actually running: Java compiler, And it will check these elements, for example: @ suppresswarnings, @ override, @ deprecated, and so on;


The generated document runs Javadoc and is parsed by a separate process. In fact, it recognizes the content, and the framework program parses the annotation during runtime of spring MVC and hibernate annotations, as for the initialization of the operation and when it should be combined with the specific framework, we need to talk about how the so-called annotation implements the function today (again: it has no function, the function and the program decide that it is only an accessory to the several major elements described above. If he thinks that he has a function, he will never know what annotation is );


First, let's write an annotation by ourselves. Writing annotation is like writing a class. Creating a Java file is consistent with the name of Annotation. It will also generate a class file, indicating that it is also Java, it only started with interface, abstract class, And class. Now there is an additional @ interface. It can be seen that it is a new object that can be recognized by JVM, just like the mark of the serialized interface, we simply write one:

The following code may seem boring to you, and then you may find something interesting:

import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.METHOD, ElementType.CONSTRUCTOR , ElementType.FIELD , ElementType.TYPE})public @interface NewAnnotation {  String value() default "";}


The above annotation indicates:

During runtime, it will be used (retentionpolicy describes other source and class levels), which can be annotated to methods, constructor, attributes, types, and classes. The name is: newannotation, which has a property of the value type, is of the string type, the default value is a Null String, that is, you can not pass the parameter.


For example:

public class A {   @NewAnnotation   private String b;   @NewAnnotation(value = "abc")   public void setB() {...}}

So many people will ask here, what is the purpose of this writing? It seems that it is useless. I didn't understand it too much here for the first time, and I saw spring MVC doing so many functions. What is the problem?


In the framework of some projects, I gradually found some functions. If there is a code accessory, it will make the framework more beautiful and concise, so I think of spring, spring's AOP is implemented based on bytecode enhancement technology, and the implementation of interceptor is no longer a myth. In turn, if annotation can be parsed, annotation-based injection is very simple and clear, as does hibernate. Of course, I will not discuss some resolution cache problems, because it will not let every object be parsed this way, we will try our best to make the performance better. Here we only talk about his principle.

Here we use a simple request object to convert it to a JavaBean object. If we use do as the suffix, the parameter names and actual attributes of some requests are not the same (the requirements are generally the same ), in network transmission, the frontend date of a project is submitted to the backend in milliseconds, but must be converted to the corresponding string format for processing. The submission contains: string, Int, integer, long, long, string [] data types. We can extend the date. With these small requirements, we can simply write one:

Import Java. lang. annotation. elementtype; import Java. lang. annotation. retention; import Java. lang. annotation. retentionpolicy; import Java. lang. annotation. target; @ retention (retentionpolicy. runtime) @ target ({elementtype. field}) Public @ interface reuqestannotation {string name () Default ""; // input parameter name Boolean datestring () default false; // whether it is of the datestring type}

Here, annotation is name, datestring, and both have default values. Name is the parameter name in the request. Otherwise, the attribute name is used as the primary parameter, whether the datestring attribute is a date string (the date previously described will change to a millisecond value, so it needs to be automatically converted ).

Then we write a do:

Import XXX. xxx. reuqestannotation; // The import part should reference the public class requesttemplatedo {private string name; @ reuqestannotation (name = "myemail") Private string email; private string DESC according to the project; @ reuqestannotation (datestring = true) Private string inputdate; private integer int1; private int int2; Public int getint1 () {return int1;} public int getint2 () {return int2 ;} public String getinputdate () {return inputdate;} Public String getname () {return name;} Public String getemail () {return email;} Public String getdesc () {return DESC ;}}

Note that the set method is not written here. To illustrate the problem, instead of how to call the set method, we directly set the value using the attribute, which can be set like private, the following is a conversion method:

If there is an httputils, We will write a static method:

/*** Get the corresponding object through the request * @ Param <t> * @ Param Request * @ Param clazz * @ return * @ throws illegalaccessexception * @ throws instantiationexception */@ suppresswarnings ("unchecked ") public static <t extends Object> T convertrequesttodo (httpservletrequest request, class <t> clazz) throws instantiationexception, illegalaccessexception {object = clazz. newinstance (); field [] fields = clazz. getdeclar Edfields (); For (field: fields) {field. setaccessible (true); string requestname = field. getname (); reuqestannotation requestannotation = field. getannotation (reuqestannotation. class); Boolean isdatestring = false; If (requestannotation! = NULL) {If (stringutils. isnotempty (requestannotation. Name () requestname = requestannotation. Name (); isdatestring = requestannotation. datestring ();} class <?> Clazzf = field. GetType (); If (clazzf = string. Class) {If (isdatestring) {string datestr = request. getparameter (requestname); If (datestr! = NULL) {field. set (object, datetimeutil. getdatetime (new date (Long. valueof (datestr), datetimeutil. default_date_format);} else {field. set (object, request. getparameter (requestname);} else if (clazzf = integer. class) field. set (object, getinteger (request. getparameter (requestname); else if (clazzf = int. class) field. set (object, getint (request. getparameter (requestname); else if (clazzf = long. class) field. set (object, getlongwapper (request. getparameter (requestname); else if (clazzf = long. class) field. setlong (object, getlong (request. getparameter (requestname); else if (clazzf = string []. class) field. set (object, request. getparametervalues (requestname);} return (t) object ;}


Here, we will fill in the corresponding value of the request to the data and return the corresponding do, and the Code uses:

RequestTemplateDO requestTemplateDO = HttpUtils.convertRequestToDO(request , RequestTemplateDO.class);

Note: This part of spring has been written for us, but I am talking about the general principle. In addition, the implementation of spring is different from that of this part, and it is more complete. Here we only want to explain some problems. Spring can assemble this do after intercepting it in the interceptor, so in spring MVC, it can be passed directly as an extension parameter into our business method. First, we know the annotation of the business method, after determining the method based on the URL, obtain the parameter list. Based on the parameter type, if it is business do, then fill the business do. hibernate can also perform inference in the same way.


OK, it seems very simple. If you really think it is simple, then you will understand it. What's special is inheritance. It seems that annotation rarely inherits, however, when I met some of my friends who wanted to modify some of the design requirements or their own design defects, I would have encountered that most of the properties of multiple do items were the same, if you do not abstract the parent class, you need to modify many do attributes at the same time, and most of the operations are performed on these shared attributes, so I still want to use the upstream styling to complete code versatility and maintain polymorphism. At that time, I was really confused, because it was based on some frameworks similar to annotation, such as Hibernate, later, I did a lot of tests with questions and matched the materials. If annotation is at the class level and constructor level, it will not be owned by the quilt class, that is, when the subclass passesXxx. Class. getannotation (xxxannotation. Class)But public methods and public attributes are acceptable. Secondly, if the subclass overrides a property or method of the parent class, no matter whether the subclass has written annotation or not, all annotation attributes of the parent class or methods in this subclass are invalid. That is, if the parent class has a property A, there are two annotation, if a is public, the subclass can inherit this attribute and annotation. If the subclass also has an A attribute, regardless of whether a has annotation, the annotation in the parent class will become invalid in the subclass.

This is why I say annotation is a property, method, package... Is bound to these elements, rather than having actual functions. When rewriting, it will be overwritten. When attributes and methods are overwritten, its annotation is also overwritten, instead of being overwritten separately according to annotation. So to solve the problem, I told him that the only method to use is public. Otherwise, there is no way, that is, reflection does not work, because hibernate cannot find this field, and there is no chance to provide the setaccessible capability, because these fields are invisible at this time, however, you can see these fields through the parent class. This is the technical level. Otherwise, only the modification design is the best method.

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.