Basic principles of Java annotations (annotations)

Why use annotations?

Early versions of Spring configured the entire framework through XML files. A reduced version of the configuration file is as follows

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans">
    <!-- Configure transaction manager -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!-- Configuration annotation-driven transaction management -->
    <tx:annotation-driven transaction-manager="transactionManager"/>
</beans>

The shortcomings of this centralized configuration are also obvious: when there is a lot of configuration information, the configuration file will become larger and larger and difficult to view and manage, especially when multiple people collaborate on development, it will cause a certain amount of mutual interference.

Nowadays, decoupling, lightweighting or miniaturization are advocated, so annotations comply with this demand. Each package or module can use annotations on internal methods or classes to achieve specified functions, and it is very convenient to use and easy to understand. . The disadvantage is that it is inconvenient for unified management. If you need to modify a certain type of function, you need to search and modify it one by one, which is distributed in every corner.

Spring annotations replaced the previous Spirng xml file. Does it mean that spring's xml is also a kind of metadata? Yes, spring's configuration file xml is also a form of metadata. However, the XML method is centralized metadata and does not need to be bound to the code, while annotations are a decentralized metadata setting method.

There has been debate for many years about the two different configuration modes of "annotations" and "XML". Each has its own advantages and disadvantages. Annotations can provide greater convenience and are easy to maintain and modify, but have a high degree of coupling . Compared with XML, Annotations are the opposite.

What are annotations?

There is such a sentence in the java.lang.annotation.Annotation interface to describe "annotations".

The common interface extended by all annotation types

This sentence is a bit confusing, and I don’t understand it personally.

An annotation in Java is actually a label written on an interface, class, attribute, or method, or a special form of annotation. The difference from ordinary // or /**/ annotations is that an ordinary annotation is just an annotation. Annotations can be read by reflection when the code is running and corresponding operations can be performed . If reflection or other checks are not used, the annotations have no real effect and will not affect the normal running results of the program. To put it simply: annotations provide a way to set metadata for program elements .

@Override is an annotation. Its essence is public interface Override extends Annotation {}. The essence of an annotation is an interface that inherits the Annotation interface . Regarding this, you can decompile any annotation class and you will get the result.

Its function is to tell readers (developers, compilers) that this method overrides the method of the parent class. It is just a sign for developers, and the compiler will do more things. If the compiler finds that the method is marked with this annotation , it will check whether this method really overrides the method of the parent class.

The annotations added in the spring framework will affect the running of the program because spring internally uses reflection to operate the corresponding annotations.

Program elements refer to interfaces, classes, attributes, and methods. These are all elements that belong to the program. So what is metadata?

metadata

Meta data is data that describes data (data about data). For example, for the storage of jpeg or PNG image description data, please refer to " JPEG/Exif/TIFF Format Interpretation (2): Picture Metadata Saving and EXIF ​​Detailed Explanation  " and " PNG File Interpretation (2): PNG Format File Structure and Data Structure Interpretation— Decoding PNG data

  • Metadata is additional information added to program elements such as methods, fields, classes, and packages. Annotations are a form of carrier.

  • Annotations cannot directly interfere with the running of program code.

Take a look at the official information: https://www.oracle.com/technetwork/articles/hunter-meta-097643-zhs.html

the term definition
metadata Data about data. The goal of JSR-175 is to provide metadata facilities in the Java language.
annotation A special Java construct used to modify a class, method, field, parameter, variable, constructor, or package. It is the tool chosen by JSR-175 to provide metadata.
Annotation type Various named annotations with special implementation
Attributes A special metadata item specified by an annotation. Sometimes used interchangeably with comments

Java's new metadata tools provide a standard way to annotate Java code from within the Java code. It enables you to place descriptive metadata next to the element you want to describe.

Annotation is the metadata we add to the code. Using annotations can write more concise and clean code, and can also perform type checking at compile time .

The role of JAVA annotations

  • As a specific tag, used to tell the compiler some information

  • Dynamic processing at compile time, such as dynamically generating code

  • Dynamic processing at runtime, as a carrier of additional information, such as obtaining annotation information

Classification of annotations

Generally speaking, annotations are divided into the following three categories:

  • Meta-annotation  – Java’s built-in annotation, indicating the usage scope, life cycle, etc. of the annotation.

  • Standard annotations  – Basic annotations provided by Java, marking expired elements/marking methods that override parent class methods/marking to suppress warnings.

  • Custom annotations  – Annotations defined by third parties, whose meanings and functions are defined and implemented by the third party.

meta-annotation

Meta-annotations are annotations used to define annotations . They are usually used in the definition of annotations to indicate the usage range, effective range, etc. of the annotation. Meta XX represents the most basic and primitive things. Therefore, meta annotations are the most basic and non-decomposable annotations. We cannot change them and can only use them to define custom annotations .

Meta-annotations include the following five types: 

  1. @Retention: life cycle of annotation

  2. @Target: The target of the annotation

  3. @Inherited: Whether subclasses are allowed to inherit this annotation

  4. @Repeatabl: Whether annotations can be repeated.

  5. @Documented: Whether the annotation should be included in the JavaDoc document

The most commonly used ones are @Retention and @Target. Below are the five meta-annotations introduced below.

@Retention

The Chinese translation means reserved, indicating the life cycle of custom annotations.

@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.ANNOTATION_TYPE)
public @interface Retention {
    RetentionPolicy value();
}

The main cycle from writing Java code to running is source file → Class file → runtime data. @Retention marks the stage to which the custom annotation information should be retained . The corresponding value is SOURCE → CLASS → RUNTIME.

  • SOURCE  source code java file, the annotation is visible during compilation and discarded when it is included in the generated class file.

    One of the simplest uses is to customize an annotation such as @ThreadSafe to mark a class as thread-safe. It has the same effect as annotation, but it is more eye-catching.

  • Annotations will be retained in the CLASS  class file, but will disappear when the jvm is loaded and run (discarded during the class loading phase)

    Personally, I think it mainly plays a marking role, and I haven't done any experiments yet. For example, if you mark a @Proxy, the corresponding proxy class will be generated when the JVM is loaded.

  • When RUNTIME  is running, if you want to use reflection to obtain annotation information, you need to use RUNTIME. Reflection is performed during the running phase. Save permanently

    Reflection is executed in the running phase, so only the life cycle of the Runtime will be retained until the running phase and can be read by reflection, which is what we most commonly use.

@Target

Chinese translation is the target, describing the scope of use of the custom annotation - who is the target of the effect. That is to say, are your annotations used to modify methods? Modification type? It is also used to modify field attributes.

Allow custom annotations to be marked on which Java elements (classes, methods, attributes, local attributes, parameters...)

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface MyAnnotation {
    String description() default "";
}

@MyAnnotation
public class AnnotationTest {
    // @MyAnnotation will report an error if used on attributes
    public String name;

    @MyAnnotation
    public void test(){}

}

value is an array and can have multiple values, indicating that the same annotation can be used to annotate different elements at the same time. The value of value is as follows

value illustrate
TYPE Classes, interfaces, annotations, enumerations
FIELD Attributes
MEHOD method
PARAMETER method parameters
CONSTRUCTOR Constructor
LOCAL_VARIABLE Local variables (such as loop variables, catch parameters)
ANNOTATION_TYPE annotation
PACKAGE Bag
TYPE_PARAMETER Generic parameters jdk1.8
TYPE_USE any element jdk1.8

@Inherited

Whether it can be inherited by subclasses of the annotated class. Annotations modified by @Inherited are inheritable. When a custom annotation is annotated to a class, the subclasses of the class will inherit the custom annotation. What needs to be noted here is that annotations will be inherited only when the subclass inherits the parent class. If a class implements an interface, or an interface inherits an interface, it cannot obtain the annotation declaration on the parent interface. The correct example is as follows (obtaining annotations through reflection)

@Repeatabl

Whether the label can be repeated. This annotation is actually a syntax sugar. Before jdk1.8, there was a way to make repeated annotations, which was to use array attributes (custom annotations will be discussed).

@Documented

Whether it is reflected in the generated JavaDoc document, after the annotation is marked, the generated javadoc will contain the annotation, which will not be demonstrated here.

Standard annotation

That is, the three built-in annotations of java

  • @Override marks a method as overriding a parent class method

  • @Deprecated marks an element as expired, avoid use - it is no longer recommended and may be removed in the next JDK version.

    • Supported element types are: CONSTRUCTOR, FIELD, LOCAL_VARIABLE, METHOD, PACKAGE, PARAMETER, TYPE

  • @SuppressWarnings does not output corresponding compilation warnings

Custom annotations

The essence of annotation is an interface, and it inherits java.lang.annotation.Annotation. The internal definition is actually a method with a default value.

Annotation definition format

public @interface annotation name {
  Modifier Return value Property name() Default value;
  //TODO
}

First of all, the modifiers of annotations are generally public . Defining annotations is generally for use by three parties. What is the point of not being public? The defined type uses @interface. You can guess that it has some unclear relationship with the interface. In fact, the annotation is an interface. When the program is running, the JVM will generate the corresponding proxy class for it.

Then the internal definition is a bit different. If you say it is a method, it also has a default value. If you say it is an attribute, there is a parentheses added after it. I personally still like to call it an interface method with a default return value. We will learn more about its true nature in the following studies. The internal modifier can only be public, even if it is not written, it will be public by default, because it is essentially an interface, and the default access permission of the interface method is public.

Annotations cannot inherit or implement other classes or interfaces . They are metadata in themselves, so there is really no need.

The types supported by the return value are as follows:

  • Basic types int float boolean byte double char logn short

  • String

  • Class

  • Enum

  • Annotation

  • Array types for all of the above types

Define a simple interface example

//Keep until runtime
@Retention(RetentionPolicy.RUNTIME)
// Can be added to methods or classes
@Target(value = {ElementType.TYPE,ElementType.METHOD})
public @interface RequestMapping {
    public String method() default "GET";
    public String path();
    public boolean required();
}

Try compiling this annotation

Annotations and Reflection

Using reflection operation annotations

Reflection can obtain the Class object, and then obtain the instances of Constructor, Field, Method, etc. Click on the open source code structure to find that Class, Constructor, Field, Method, etc. all implement the AnnotatedElement interface. The methods of the AnnotatedElement interface are as follows

// Determine whether the element contains the specified annotation, if it does, return true
boolean isAnnotationPresent(Class<? extends Annotation> annotationClass)
// Return the corresponding annotation on the element, if not return null
<T extends Annotation> T getAnnotation(Class<T> annotationClass);
// Returns all annotations on the element, or an empty array if there are no annotations
Annotation[] getAnnotations();
//Return the annotation of the specified type, if not return an empty array
T[] getAnnotationsByType(Class<T> annotationClass)
//Return the annotations of the specified type. If no empty array is returned, it only contains directly annotated annotations and does not include inherited annotations.
T getDeclaredAnnotation(Class<T> annotationClass)
//Return the annotations of the specified type. If no empty array is returned, it only contains directly annotated annotations and does not include inherited annotations.
T[] getDeclaredAnnotationsByType
// Return all annotations on the element. If there are no annotations, return an empty array, which only contains directly annotated annotations and does not include inherited annotations.
Annotation[] getDeclaredAnnotations();

This means that all the above elements can obtain the annotations marked on the element through reflection.

Amway's " Analysis of the Principles of Java Reflection Mechanism "

The underlying implementation of annotations - dynamic proxy

Customize an annotation, debuger

Reference article:

From getting started to becoming proficient in Java annotations, this article is enough blog.kimzing.com/java/ From getting started to becoming proficient in Java annotations - this article is enough/

The basic principles of JAVA annotations  The basic principles of JAVA annotations - Nuggets

Reprint the article " Basic Principles of Java Annotations (Annotations) " on this site , please indicate the source: Basic Principles of Java Annotations (Annotations) - Java key review content, detailed explanation of core concepts - Zhou Junjun's personal website

Guess you like

Origin blog.csdn.net/u012244479/article/details/130049535