The computer world is made up of zeros and ones. In order to make it easier for humans to communicate with computers, our forefathers invented programming languages, which were translated into machine languages that machines could understand by compilers. Better reading the code for the convenience of human beings, to avoid unnecessary 996, almost all of the programming languages provide “annotation” feature, to some extent, the existence of “annotation” is “nonsense”, because the compiler when executed here is ignored, although “annotation” is written by human, but also just to show “stupid” human. However, there have been pioneers in every era who have done nothing more than make our code look simpler and more progressive, so the communication between humans and machines has to be further developed, and this is a comment to the compiler – “annotations”.

What is a “note”

Annotation, called Annotation, is a concept introduced in Java SE 5.0. It is a type like class and interface. Many developers think annotations have a low status, but they don’t. Annotations like @Transactional, @Service, @RestController, @RequestMapping, @Crossorigin, and so on are becoming more and more common.

Having said all this, what exactly are “notes”?

Annotations are special “comments” that precede classes, methods, fields, and parameters in Java source code.

Without further ado, go directly to the code:

// The user requests the interface
@RestController
public class UserController {
    @GetMapping(value = "/user")
    public User getUser(a) {
        return new User("RunTu".22."Male"); }}Copy the code

This is a very simple SpringBoot controller code. The first line is “comment”, which tells the reader that this is a user request interface; Lines 2 and 4 are “annotations” for the compiler, a Restful interface that requests the method Get and matches the path “/user”.

Annotations are ignored by the compiler, and annotations can be packaged by the compiler into a class file, so annotations are a kind of “metadata” used as annotations. From the JVM’s point of view, annotations themselves have no effect on the code logic, and how they are used is entirely up to the tools.

The nature of annotations

Before we get into the nature of annotations, we need to understand that annotations are a type, just like classes and interfaces, so if we want to declare an Annotation, we also need to write a Java file to create the Annotation. Creating annotations is simple, as shown in the following code 👇

import java.lang.annotation.*;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface TestOverride {
}
Copy the code

Create an annotation named “TestOverride” with the keyword ** “@interface” **. No hurry, here we temporarily press the no table, later to explain.

Getting back to the point, since this is a testoverride.java file, we can generate the bytecode file using the javac command, decompile the resulting bytecode file using the Javap command, and see what happens.

See if it’s a bit of an Epiphany that an Annotation is essentially an interface that inherits the Annotation interface.

In fact, we can look at the JDK source code for humans to see the “comments” can also get a glimpse.

The common interface extended by all annotation types

Take out this sentence translation is:

A common interface inherited from all annotation types

To go back to the beginning, a comment is a special comment for the compiler to see, and it’s not even a comment without the code to parse it.

Use notes

Annotations that parse a class or method often take two forms, a compile-time scan and a run-time reflection. We’ll explain how to combine annotations with reflection later, starting with compiler scanning.

“Privilege” notes

Compile-time scanning is when the compiler detects that a class or method has been modified with some annotations during compilation of Java code into bytecode, and then it performs some processing on those annotations. Typically, only a few annotations within the JDK can enjoy this privilege.

In the case of @Override, once the compiler detects that a method has been modified with the @Override annotation, the compiler checks to see if the method signature of the current method actually overrides a method of the parent class, that is, if there is an identical method signature in the parent class.

Custom annotations

In most cases, the compiler does not know what the annotation actually does, so it is up to the developer to specify the scope of the annotation if it is compiled into the bytecode file. And this, will involve in another knowledge point – meta annotation.

Yuan notes

“Yuan” has the initial meaning in Chinese. Meta annotations are annotations that modify annotations. Take the @target and @Retention annotations in the above example. The JDK already has some meta annotations built in, so you just need to use them, and usually don’t need to write them yourself. Meta-annotations typically serve to specify an annotation lifecycle and its target.

In the JDK, there are four meta-annotations:

  • @target: The Target of the annotation
  • @Retention: The life cycle of annotations
  • Documented: Whether an annotation should be included in a JavaDoc document
  • @Inherited: Whether a child class is allowed to inherit this annotation

@documented and @Inherited are rarely used in practice, so here we’ll explain @target and @Retention in detail.

@Target

We can also see from the name that the annotation is used to specify the target, i.e. does your annotation modify a method or a class? , of course, can not only modify the two, in the source code in Java. Lang. The annotation. ElementType enum constants, said as shown below.

  • Elementtype. TYPE: Allows modified annotations to be applied to classes, interfaces, and enumerations
  • Elementtype. FIELD: Allows action on attribute fields
  • Elementtype. METHOD: Allows action on methods
  • Elementtype. PARAMETER: Allows action on method parameters
  • Elementtype. CONSTRUCTOR: Allows action on a CONSTRUCTOR
  • Elementtype. LOCAL_VARIABLE: Allows action on local variables
  • Elementtype. ANNOTATION_TYPE: Allows annotation
  • Elementtype. PACKAGE: Allows action on packages

Going back to the @target annotation, the JDK defines it as follows:

We can pass the scope value for @target in the following way

@Target(value = {ElementType.FIELD})
Copy the code

@Retention

@ Retention is used to indicate the current annotation life cycles, and @ Target, need to accept a parameter is used to specify the corresponding life cycle, is also an enumeration type, using Java. Lang. The annotation. RetentionPolicy enumerated constants, said respectively as follows:

  • Retentionpolicy. SOURCE: The current annotation is visible at compile time and is not written to the class file
  • Retentionpolicy. CLASS: discarded during CLASS loading and written to the CLASS file
  • Retentionpolicy. RUNTIME: permanently saved and can be retrieved by reflection

Going back to the @Retention annotation, the JDK defines it as follows:

In general, if we set our own custom annotations, we usually choose to use retentionPolicy.runtime so that we can easily fetch them by reflection in subsequent code and add some custom functionality to them.

Annotations and reflections

Mentioned annotations, nagging is the reflection of but in fact we have thing is we need to pay attention to the existence of annotation and reflection, there is no relationship, even if there is no reflection, you can still define an annotation, but does not have what effect on your code, and because of that, we only need through reflection to obtain annotations and provides the concrete operating logic.

reflection

Reflection is what, don’t know the friend to read this article 👉 www.liaoxuefeng.com/wiki/125259…

Here I simple example to help you understand, Java is a local tyrants safe, if you go directly to open the safe local tyrants is not allowed, but if you carry a gun on his head to let him open the box, then you can get the money in the box, this gun is “reflection”, can make it easier for you normally don’t have access to content.

Deal with annotations

As mentioned above, annotations are essentially bytecode files when compiled and can be retrieved by reflection. The JDK also provides apis for parsing annotations, such as:

  • The Class object’s isAnnotationPresent() method determines whether a specified annotation is applied to the Class.
  • The annotation object is obtained using the getAnnotation() method.

When you get the annotation object, you can get the value of the property that was defined when the annotation was used. This piece of content already has a lot of people have written, specific what is called the API, not reinvent the wheel here, details can be read 👉 www.liaoxuefeng.com/wiki/125259…

Sample code is shown below:

@CrossOrigin(origins = "http://qingmiaokeji.com", allowedHeaders = "accept,content-type", methods = { RequestMethod.GET, RequestMethod.POST })
public class TestController {
	public static void main(String[] args) {
		Class c = TestController.class;

		if(c.isAnnotationPresent(CrossOrigin.class)) { CrossOrigin crossOrigin = (CrossOrigin) c.getAnnotation(CrossOrigin.class);  System.out.println(Arrays.asList(crossOrigin.allowedHeaders())); System.out.println(Arrays.asList(crossOrigin.methods())); System.out.println(Arrays.asList(crossOrigin.origins())); }}}// Output: [accept,content-type]
// [GET, POST]
// [http://qingmiaokeji.com]
Copy the code

Annotations and XML

As the Spring ecosystem dominates Java development today, one of the features of Spring is the substitution of annotations for XML configurations, which inevitably leads to a discussion between XML configuration and annotations configuration.

  • Note: this is distributed metadata that is tightly bound to source code.
  • XML: Is centralized metadata with no binding to source code.

Therefore, the choice of annotations and XML can be viewed from two perspectives: decentralized or centralized, and source-bound/unbound.

Using XML requires parsing individual files, which is less efficient than using reflection to get annotations, but more flexible; Using annotations can reduce maintenance costs, but if annotations need to be changed, the entire project needs to be recompiled, and the increased number of annotations can have an impact on the simplicity of the code.

So, having said that, we come back to the old point that there is no perfect technology, only the right technology, whether it’s using annotations or XML, doing those things, annotations and XML are not a panacea, just meet your needs and solve the problem in a simpler way.