1. Introduction to reflection

1.1 reflection

Reflection is the ability of a program to access, detect, and modify its own state or behavior.

1.2 Java’s reflection mechanism

Java’s reflection mechanism means that in the running state of a program, given any class, can get the properties and methods of this class; Given any object, the properties and methods of that object can be called. This dynamic ability to obtain information about the class and call methods of the object is called Java’s reflection mechanism. In short: Reflection allows you to take the properties and methods of any class and call them while the program is running.

1.3 Main functions of Java reflection

  • The runtime constructs an object of a class;
  • Get the member variables and methods that a class has at runtime;
  • Calls methods on any object at runtime;
  • Generate dynamic proxy; In fact, the main function of reflection I think is to work with frames.

1.4 the Java class type

To understand reflection, you first need to know the Class, whose full name is Java.lang.class. Java is an object-oriented language, and everything is an object. Even if it is powerful enough for one Class, it is still an object of another Class. In other words, a normal Class is an object of Class, i.e. Class is a Class of all classes. For normal objects, we create them like this:

Code code1 = new Code();
Copy the code

All classes are objects of Class. How can we express this by:

Class c = new Class();
Copy the code

But when we look at the source code for Class, it reads:

private Class(ClassLoader loader) { 
    classLoader = loader; 
}
Copy the code

As you can see, the constructor is private, and only the JVM can call this constructor to create a Class object. Therefore, we cannot create a Class object like a normal Class. Although we cannot create a Class object, we can obtain a Class object from an existing Class.

Class c1 = Test.class; Class c2 = test.getClass(); class c2 = test.getClass();testClass C3 = class.forname (); Class c3 = class.forname ();"com.catchu.me.reflect.Test"); This method is a Class Class callforThe Name method, obtained by the fully qualified Name of a classCopy the code

Here, C1, C2, and C3 are all Class objects. They are identical and have a Class type called Test. C, c, C, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c, c Why is it called Test? Here don’t obsess over the whether or not they are the same, as long as the understanding of class type is stem what of, as the name suggests, the class type is the class type, is also describe what a class is, what are the things, so we can know a class by class type attributes and methods, and can be called a kind of attributes and methods, which is the basis of reflection. Example code:

public class Test {

    public static void main(String[] args) throws ClassNotFoundException {
        Class<Test> class1 = Test.class;
        System.out.println("Class name 1:"+class1.getName());

        Test Test = new Test();
        Class<? extends Test> class2 = Test.getClass();
        System.out.println("Class name 2:"+class2.getName()); Class<? > class3 = Class.forName("com.catchu.me.reflect.Test");
        System.out.println("Class name 3:"+class3.getName());
        if(class1==class2){
            System.out.println("class1==class2");
        }
        if(class1==class3){
            System.out.println("class1==class3"); }}}Copy the code

Output results:

The name of the class 1: com. Catchu. Me. Reflect the Test class name 2: com. Catchu. Me. Reflect. The Test class name 3: com.catchu.me.reflect.Test class1==class2 class1==class3Copy the code

2. The operation of reflection

Class and java.lang.reflect. We have obtained the Class information of a Class, and we can use certain methods to manipulate the following information of the Class:

2.1 Operation constructors

Everything has its object, the Constructor of a Class is the Java lang. Reflect. The Constructor Class object, through the following methods can obtain the Constructor Class objects:

public Constructor<T> getDeclaredConstructor(Class<? >... ParameterTypes) public Constructor<T> getConstructor(Class<? Constructor) >... ParameterTypes) // obtain all public constructors for this class, including the parent class // Constructor<? >[] allConstructors = class1.getDeclaredConstructors(); // Constructor<?; // Constructor<? >[] publicConstructors = class1.getConstructors(); Public Constructor<? > constructor = class1.getDeclaredConstructor(String.class); // Constructor publicConstructor = class.getConstructor (string.class); // Constructor publicConstructor = class.constructor (String); // Get the public constructor for the specified declarationCopy the code

Test code is as follows:

public class TestConstructor { public static void main(String[] args) throws Exception{ Class<? > personClass = Class.forName("com.catchu.me.reflect.Person"); // Get all constructors, including private constructors, excluding Constructor<? >[] allConstructors = personClass.getDeclaredConstructors(); // Get all public constructors, including Constructor<? >[] publicConstructors = personClass.getConstructors(); System.out.println("Constructor after traversal:");
        for(Constructor c1 : allConstructors){ System.out.println(c1); } Constructor<? > c2 = personClass.getDeclaredConstructor(String.class); c2.setAccessible(true); If the constructor is public, do not set Object Person = C2.newinstance (). If the constructor is public, do not set Object Person = C2.newinstance ()."Liu Junzhong"); // Use reflection to create an object of the Person class, passing in system.out.println (person.toString()); }}Copy the code

The Person class looks like this and contains a private constructor to measure the effect:

public class Person {
    private int age;
    private String name;
    public Person() { } private Person(String name){ this.name = name; } public Person(int age,String name){ this.age = age; this.name = name; } / / omittedset/get @override public StringtoString() {
        return "Person{" +
                "age=" + age +
                ", name='" + name + '\''+'}'; }}Copy the code

The test results are as follows:

Constructor after traversal:  public com.catchu.me.reflect.Person(int,java.lang.String) private com.catchu.me.reflect.Person(java.lang.String) public  com.catchu.me.reflect.Person() Person{age=0, name='Liu Junzhong'}
Copy the code

As you can see above, after obtaining the Class type of a Class, we can obtain the constructor of that Class through the methods in the reflection package, and then we can create objects of that Class.

2.2 Manipulating member variables

Everything is an object. The member variables of a Class are objects of the java.lang.Reflect. Field Class. You can obtain a member variable of a Class by using the following methods of the Class.

Public Field getDeclaredField(String name) public Field getDeclaredField(String name) Public Field getField(String name) public Field getField(String name) Field[] allFields = class1. GetDeclaredFields (); Field[] publicFields = class1. GetFields (); Field ageField = class1. GetDeclaredField ();"age"); Field desField = class1. GetField ()"des"); // Get the public attribute specified by classCopy the code

The example code is as follows:

public class TestField { public static void main(String[] args) throws Exception{ Class<Person> personClass = Person.class; / / get all the member variables, including private Field [] allFields = personClass. GetDeclaredFields (); // Get all public member variables, including the parent class Field[] publicFields = personClass.getFields(); System.out.println("All member variables:");
        for(Field f : allFields){ System.out.println(f); } / / get the value of a variable / / create the object instance Constructor < Person > c = personClass. GetDeclaredConstructor (String. Class); c.setAccessible(true); // Since the constructor is private, we need to make the Person accessible here Person = c.newinstance ()."Liu Junzhong"); / / get variable name object Field Field = personClass. GetDeclaredField ("name");
        field.setAccessible(true); // Since the name variable is private, it needs to be made accessible here. Object value = field.get(person); Object value = field.get(person); //String name = person.getName(); System.out.println(The value of the obtained variable is:+value); }}Copy the code

The output is as follows:

All member variables: Private int com. Catchu. Me. Reflect. Person. Age private Java lang. String com. Catchu. Me. Reflect the Person. The name for the value of the variable is: Liu JunchongCopy the code

Notice the field.get(person) method here. The usual way to get an attribute from an object is by: String name = person.getName(). Field.get(object), which also gets a field of an object, somewhat similar to the Invoke method.

2.3 Operating member Methods

Everything is an object. The member methods of a Class are objects of java.lang.reflect.Method. The member methods of a Class can be obtained through the following methods of the java.lang.Class Class.

public Method getDeclaredMethod(String name, Class<? >... Public Method getMethod(String name, Class<? >... ParameterTypes) / / get the class all public methods, including parent / / specific use Method [] the methods = class1. GetDeclaredMethods (); Method[] allMethods = class1. GetMethods (); Method = class1. GetMethod (); // getMethod();"info", String.class); Class1.getdeclaredmethod = class1.getDeclAredMethod (declaredMethod = class1.getDeclAredMethod (declaredMethod = class1.getDeclAredMethod);"info", String.class); // Return the method of the Class corresponding to this Class object with the specified parameter listCopy the code

Test code is as follows:

public class TestMethod {
    public static void main(String[] args) throws Exception {
        Person person = new Person();
        Class<? extends Person> personClass = person.getClass();
        Method[] allMethods = personClass.getDeclaredMethods();
        Method[] publicMethods = personClass.getMethods();
        System.out.println("Traverse all methods:");
        for(Method m : allMethods){ System.out.println(m); } Person person2 = personClass.newinstance (); Person person2 = personClass.newinstance (); Method Method = personClass.getMethod() Method = personClass.getMethod() Method = personClass."study", int.class, String.class);
        Object o = method.invoke(person2, 18, "Liu Junzhong"); }}Copy the code

Test results:

Iterating over all methods:  public java.lang.String com.catchu.me.reflect.Person.toString() public java.lang.String com.catchu.me.reflect.Person.getName() public void com.catchu.me.reflect.Person.setName(java.lang.String) public void com.catchu.me.reflect.Person.study(int,java.lang.String) public int com.catchu.me.reflect.Person.getAge() public void Com. Catchu. Me. Reflect. Person. SetAge (int) I'm Liu Junchong, I am 18, and I'm learning reflectionCopy the code

Object o = method.invoke(Person2, 18, “person2 “); This is to call the method method of the Person2 object in the format: method name. invoke(object, parameter), similar to the get method used to get the value of a member variable. From the above, we can see the power of reflection: through reflection we can get the Class type, through Class type we can get the constructor, and then instantiate a new object; Member variables and methods can be obtained by reflection, and the values of these member variables can be obtained or member methods can be called by the object being instantiated. This is only part of the reflection. We can also use reflection to determine whether a class, variable, or method contains certain annotations. We can also use reflection to dynamically proxy other methods. Let’s look at some of the most common apis for reflection, and finally show how reflection can be used in combination with annotations and dynamic proxies.

2.4 Other Methods

  • Common methods used in annotations:
Annotation[] annotations = (Annotation[]) class1.getAnnotations(); Class = (Annotation) class1. GetAnnotation (Deprecated. Class); / / get the class object specified annotation Type genericSuperclass = class1. GetGenericSuperclass (); / / retrieve class object directly superclass Type Type [] interfaceTypes = class1. GetGenericInterfaces (); // Get all the interfaces of the class objecttypeA collection ofCopy the code
  • To obtain other information about a Class object:
boolean isPrimitive = class1.isPrimitive(); Bool isArray = class1. IsArray (); Boolean isAnnotation = class1. IsAnnotation (); Boolean isInterface = class1. IsInterface (); Boolean isEnum = class1. IsEnum (); Bool isAnonymousClass = class1. IsAnonymousClass (); / / judge whether an anonymous inner class Boolean isAnnotationPresent = class1. IsAnnotationPresent (Deprecated. Class); String className = class1. GetName (); Package aPackage = class1. GetPackage (); String simpleName = class1. GetSimpleName (); Class1. GetModifiers (); // getModifiers(); Class<? Class<? >[] declaredClasses = class1.getDeclaredClasses(); // Inner Class<? > declaringClass = class1.getDeclaringClass(); ClassLoader = class1. GetClassLoader () returns the ClassLoader getSuperclass() : gets all the superclasses of a class getInterfaces() : gets all the implemented interfaces of a classCopy the code

3. Dynamic proxy

Proxy operations are implemented in the java.lang.reflect.Proxy class, using the Proxy’s newProxyInstance() method to create a Proxy object, as follows:

Public static Object newProxyInstance(ClassLoader, class <? >[] interfaces,InvocationHandler h)Copy the code

Don’t be afraid of a big piece of obscure code. There’s a trick to it. It’s all templates, and we just pass what we need. You can see that you need three parameters, the classloader, the interface, and the call handler. Class.getclassloader (); class.getClassLoader (); class.getInterfaces (); Now all you have to do is create an InvocationHandler object. In fact, this is where the core code for our dynamic proxy is written. The template I mentioned above is actually the following steps:

  1. Write the Proxy class and method, in the Proxy method to implement proxy.newProxyInstance ();
  2. The parameters required in the proxy are: class.getClassLoader() for the class being represented, new class [] {interface-.class} for all implementations of the class being represented, and new InvocationHandler() for the handle method;
  3. Override the Invoke Method in a handle Method. The input to the invoke Method takes three parameters: Object proxy, Method Method,Object[] args, and Object[] args. In this Method, We can customize our business;
  4. Get the proxy class and force it into the interface being represented.
  5. Finally, we can call any method of the interface as if it were not proxyed. after the method is called, the method name and parameter list will be passed to the invoke method of the proxy class, and the logical flow of the new business will occur. Look at the following example code: Interface PersonInterface:
public interface PersonInterface {
    void doSomething();
    void saySomething();
}
Copy the code

The implementation class of the interface:

public class PersonImpl implements PersonInterface {
    @Override
    public void doSomething() {
        System.out.println("Humans are doing things.");
    }
    @Override
    public void saySomething() {
        System.out.println("Humans are talking."); }}Copy the code

The proxy class:

Public class PersonProxy {public static void main(String[] args) {final PersonImpl person = new PersonImpl(); PersonInterface proxyPerson = (PersonInterface) Proxy.newProxyInstance(PersonImpl.class.getClassLoader(), PersonImpl.class.getInterfaces(), newInvocationHandler@override public Object Invoke (Object proxy, Method Method, Method) { Object[] args) throws Throwable {if(method.getName()=="doSomething"){
                            person.doSomething();
                            System.out.println("The implementation class is called through a regular method.");
                        }else{
                            method.invoke(person,args);
                            System.out.println("Implementation class is called through the reflection mechanism.");
                        }
                        returnnull; }}); proxyPerson.doSomething(); proxyPerson.saySomething(); }}Copy the code

The execution result is as follows:

We're doing things and we're calling the implementation class through the normal methods and we're talking and we're calling the implementation class through the reflection mechanismCopy the code

When we call proxyPerson.dosomething (), we do not immediately enter the doSomething method of the implementation class. Instead, we enter our invoke method with the method name and parameters. In this case, I make a judgment, If it equals “doSomething” use a regular method call, otherwise use a reflected method call. This looks like a normal call, but every time the execution of our proxy method inside, we can do some “hands and feet” in this, to add our business processing. Take another example below. For example, a dress is normally sold for 50 yuan on Tmall, but now you are my VIP user, so I can give you a discount of 10 yuan. Other businesses are the same, except here, where the price is 10 yuan cheaper. Interface SaleService:

Public interface SaleService {// return the size of the clothes; int clothes(String size); }Copy the code

Interface implementation class SaleServiceImpl:

public class SaleServiceImpl implements SaleService {
    @Override
    public int clothes(String size) {
        System.out.println("Dress size"+size); // Simulate fetching clothing prices from the databasereturn50; }}Copy the code

Normal undiscounted call tests:

/** * @author @description */ public class OrdinaryCustom {public static void main(String[] args) { SaleService saleService = new SaleServiceImpl(); int money = saleService.clothes("XXl");
        System.out.println("The price is:"+money); }}Copy the code

Output results:

Clothing size XXl price is: 50Copy the code

ProxySale:

Public class ProxySale {public static <T> T getProxy(final int) discount, final Class<SaleServiceImpl> implementClasses, Class<SaleService> interfaceClasses){return (T)Proxy.newProxyInstance(implementClasses.getClassLoader(),
                implementClasses.getInterfaces(), new InvocationHandler() {@override public Object Invoke (Object proxy, Method Method, Object[] args) throws Throwable { Get not discount the price of before int price = (int) method. The invoke (implementClasses. NewInstance (), args);returnprice-discount; }}); }}Copy the code

VIP user test class VipCustom:

/** * @author Liu Junzhong * @description user, */ public class VipCustom {public static void main(String[] args) {// public class VipCustom {public static void main(String[] args) { SaleService saleService = ProxySale.getProxy(discount, SaleServiceImpl.class, SaleService.class); int money = saleService.clothes("xxl");
        System.out.println("The price is:"+money); }}Copy the code

The output is:

Clothing size XXL price is: 40Copy the code

As you can see, without modifying the service provider, we have tampered with the proxy class and the results are as expected.

4. Note

4.1 Concept and Function

  1. concept
  • Annotations are metadata, the metadata of the source code
  • Annotations provide a formal way to add information to your code, making it easier to use the data later
  • An Annotation is a special modifier that is applied to classes, methods, parameters, variables, constructors, and package declarations. It is a tool chosen by the JSR-175 standard to describe metadata.
  1. role
  • Generating documentation
  • Track code dependencies, implement alternative configuration file functionality, and reduce configuration. Like some annotations in Spring
  • Format checking at compile time, such as @override
  • Whenever you create a descriptor class or interface that involves repetitive work, consider using annotations to simplify and automate the process.

4.2 Java annotations

  • What are Java annotations? In Java syntax, you start with the @ sign, followed by the name of the annotation. The package of annotations in Java is java.lang.annotation, which is used on classes, interfaces, methods, and fields. For example:
@Override
void myMethod() {... }Copy the code

Where @override is the annotation. The purpose of this annotation is to tell the compiler that the myMethod() method overrides the myMethod() method in the parent class.

  • There are three built-in annotations in Java:
Override: indicates that the current method definition will Override the method in the superclass, and the compiler will report an error if an error occurs. @deprecated: The compiler will receive a warning if this annotation is used. SuppressWarnings: Ignore compiler warnings.Copy the code
  • Meta-annotations The purpose of meta-annotations is to annotate other annotations (which are used when customizing annotations). Java5.0 defines four standard meta-annotation types that are used to provide annotations to other annotation types. Java5.0 defines four meta-annotations:
@Target
@Retention
@Documented
@Inherited
Copy the code

Java8 adds two new annotations, which I’ll cover later.

  • @Target

@target specifies the range of objects that the Annotation decorates: Annotations can be used for packages, types (class, interface, enumeration, Annotation type), type members (methods, constructors, member variables, enumeration values), method parameters, and local variables (such as loop variables, catch parameters). The use of target in the Annotation type declaration makes it clearer what target it decorates.

Function: Used to describe the scope of use of an annotation (i.e., where the described annotation can be used) values (ElementType) include:

type use
CONSTRUCTOR Used to describe a constructor
FIELD Used to describe a domain
LOCAL_VARIABLE Used to describe local variables
METHOD Used of a descriptive method.
PACKAGE Used to describe packages
PARAMETER Used to describe parameters
TYPE Used to describe classes, interfaces (including annotation types), or enum declarations

For example, if you define the following annotation, it can only be used on a method, because it is qualified as a method level annotation. If it is used on a class or other object, an error will be reported at compile time:

@Target({ElementType.METHOD})
public @interface MyMethodAnnotation {
}
Copy the code

Test class MyClass:

// @mymethodannotation public class MyClass {@mymethodannotation public voidmyTestMethod() {/ /}}Copy the code
  • @Retention

@Retention defines how long the Annotation is retained: Some annotations only appear in the source code and are discarded by the compiler; Others are compiled in class files; Annotations compiled in a class file may be ignored by the virtual machine, while others may be read when the class is loaded (note that this does not affect the execution of the class, since the annotations are used separately from the class). Using this meta-annotation allows you to limit the “lifecycle” of an Annotation.

Function: indicates the level at which the comment information needs to be saved. It is used to describe the life cycle of the comment (i.e., the scope in which the described comment is valid).

type use instructions
SOURCE Valid in the source file (i.e., source file retention) Appears only in source code and is discarded by the compiler
CLASS Valid in class files (i.e., class retention) Is compiled in a class file
RUNTIME Valid at run time (that is, run time retention) Compile in a class file

Example:

@target ({elementType.type}) // Used to describe classes, interfaces, or en@Retention (retentionPolicy.runtime) // Public @interface MyClassAnnotation { String value(); // The MyClassAnnotation annotation has a value property that you can set/get in the future}Copy the code
  • @Documented

Documented @Documented is used to describe the public API that other types of annotations should be used as members of the annotated program and can therefore be Documented by a tool such as Javadoc. Documented is a marker annotation. There are no members.

What it does: Include annotations in javadoc

java.lang.annotation.Documented
@Documented
public @interface MyCustomAnnotation { //Annotation body}
Copy the code
  • @Inherited

It’s a tag annotation that says that an annotated type is Inherited, and if an annotation type is used with the @inherited modifier for a class, then that annotation will be used for a subclass of that class, The @inherited Annotation type is Inherited by a subclass of the annotated class. Classes do not inherit annotations from the interfaces they implement, methods do not inherit annotations from the methods they override, and when the Retention of an annotation of the @inherited annotation type is RetentionPolicy.RUNTIME, The reflection API enhances this inheritance. If we use java.lang. Reflect to query an annotation of type @inherited Annotation, the reflection code check will work: Check the class and its parent classes until either the specified annotation type is found or the top-level of the class inheritance structure is reached.

Function: Allows a subclass to inherit an example annotation from its parent class. This MyParentClass uses an annotation with @inherited, so the subclass inherits this annotation message:

java.lang.annotation.Inherited
@Inherited
public @interface MyCustomAnnotation {
}

@MyCustomAnnotation
public class MyParentClass { 
  ... 
}

public class MyChildClass extends MyParentClass { 
   ... 
}
Copy the code

4.3 Custom Annotations

format

Public @interface annotation name {body}Copy the code
Annotate the supported data types of parameters:
  • All basic data types (int, float, double, Boolean, byte, char, long, short)
  • Type String
  • The Class type
  • Enum type
  • The Annotation type
  • All of the above types of arrays
The rules
  • The modifier can only be public or default
  • Parameter members can only use basic types of byte, short, int, long, float, double, Boolean eight basic types and String, Enum, Class, annotations, and the type of the array
  • If there is only one parameter member, it is best to set the name to “value”
  • An annotation element must have a definite value. A default value can be defined in the annotation or specified in the annotation. A value that is not a basic type cannot be null
  • When representing the presence or absence of an element, define a special value to represent it, such as an empty string or a negative value

Example:

@Target(ElementType.FIELD)
@Retention(value=RetentionPolicy.RUNTIME)
@Documented
public @interface MyFieldAnnotation {
    int id() default 0;

    String name() default "";
}
Copy the code

Defines a runtime valid annotation called MyFieldAnnotation for fields. It has two properties: an INT id (remember the parentheses after the ID) that defaults to 0, and a String name that defaults to “”.

4.4 Manipulation of annotations – The annotation processing library

We already know how to customize an annotation above, but the light definition is useless. The important thing is that I use it. The methods I use are very simple. Class1. IsAnnotation (), which are all methods in the AnnotatedElement interface in the Java.lang.Reflect package, has the following implementation classes:

  • Class: Class definition
  • Constructor: Constructor definition
  • Field: tired member variable definition
  • Method: Method definition of a class
  • The Java.lang. Reflect Package mainly contains utility classes that implement reflection. In fact, all of the reflection apis provided by the java.lang. Reflect Package extend the ability to read run-time Annotation information. When an Annotation type is defined as a run-time Annotation, the Annotation is visible to the run time, and the Annotation stored in the class file when the class file is loaded is read by the virtual machine. The AnnotatedElement interface is the parent interface for all program elements (Class, Method, and Constructor), so after the program gets the AnnotatedElement object for a Class through reflection, The program can call one of the following four methods on the object to access the Annotation information:
  1. Method 1: T getAnnotation(Class annotationClass): Returns an annotation of the specified type that exists on a program element, or null if the annotation of the type does not exist.
  2. Method 2: Annotation[] getanannotations (): Returns any annotations that exist on this program element.
  3. Method 3: Boolean is AnnotationPresent(Class
    annotationClass): Determines whether the program element contains an Annotation of the specified type, returning true if it does, false otherwise.
  4. Method 4: Annotation[] getdeclaredanannotations () : Returns any annotations that directly reside on this element. Unlike other methods in this interface, this method ignores inherited comments. (If no comment exists directly on the element, an array of length zero is returned.) The caller of the method can modify the returned array at will; This has no effect on the arrays returned by other callers. Conclusion: custom annotation with Java. Lang, the annotation. The annotation, operation annotations in Java. Lang. Reflect. AnnotatedElement

The test code CustomClassAnnotation looks like this:

/** * @target (elementType.type); // @target (elementType.type); Public @Interface CustomClassAnnotation {String} @Retention(RetentionPolicy.runtime) // Valid at RUNTIME @Documented // Documentation visible public @interface CustomClassAnnotation {String value(); // Get annotation name}Copy the code

The FruitName class is as follows:

/** * @retention (RetentionPolicy.runtime) */ @target (elementType.field) // @retention (RetentionPolicy.runtime) @Documented public @interface FruitName { String name() default"";
}
Copy the code

FruitColor class is as follows:

/** * @retention (RetentionPolicy.runtime) */ @target (elementType.field) @Retention(RetentionPolicy.runtime) Documented public @interface FruitColor {// Documented public @interface FruitColor; // Default Color (); }Copy the code

The Fruit entity class looks like this:

/**
 * @author 刘俊重
 * @Description Fruit实体类
 */
@CustomClassAnnotation(value="fruit")
public class Fruit{

    @FruitName(name="apple")
    private String name;

    @FruitColor(color= FruitColor.Color.RED)
    private String color;

}
Copy the code

The test class TestAnnotation looks like this:

/** * @author * @description */ public class TestAnnotation {public static void main(String[] args) { Class<Fruit> clazz = Fruit.class; / / reflection for Class object CustomClassAnnotation annotation = clazz. GetAnnotation (CustomClassAnnotation. Class); // Get the Fruit class annotationif(null! =annotation &&"fruit".equals(annotation.value())){
            System.out.println("The name of the Fruit class annotation is ======."+annotation.value()); Field[] allFields = clazz.getdeclAredFields ();for(Field field : allFields){
                if(field. IsAnnotationPresent (FruitName. Class)) {/ / judge whether there is any FruitName annotation FruitName FruitName = field.getAnnotation(FruitName.class); System.out.println("Name of fruit ====="+fruitName.name());
                }
                if(field.isAnnotationPresent(FruitColor.class)){
                    FruitColor fruitColor = field.getAnnotation(FruitColor.class);
                    System.out.println("Fruit Color ====="+fruitColor.color()); }}}else{
            System.out.println("Comment value wrong, please check."); }}}Copy the code

Summary: Annotations can be used to obtain class names, interface names, method names, property names, with reflection to dynamically generate objects, with dynamic proxy, to dynamically call certain methods, this is basically part of the underlying implementation principle of the Spring framework. Note: Some of the quotes in this article are from http://t.cn/RK8ci8w. The original author did a good job with reflections and notes. I have refined some of the content and rewritten some of the examples. I added the dynamic proxy part, thinking about reflection, proxy, and annotations all in one.

Attached a personal wechat public account, welcome to communicate with me.