Calling annotated methods through reflection

Keywords: Java Spring jvm Eclipse

When I was learning Spring Aop, I learned that the underlying implementation of spring is basically annotation plus reflection.It's like writing your own very small test code and trying it out.But there are some minor episodes in the process.

 

I want to invoke the @Tag marked part of the method held by an object through reflection. Here is my code:

import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.reflect.Method;
import java.lang.annotation.RetentionPolicy;


public class Test {
	public static void main(String[] args) throws Exception {
		Class<Test> t=Test.class;   //Get Class Object
		Method[] m=t.getMethods();  //Get a collection of methods
		for(Method mm : m) {        //traversal method
			if(mm.toString().contains("m("))   //Printing Test Method
				System.out.println("\nmethod print:\t"+mm);
			for(Annotation a : mm.getAnnotations()) {   //Traversal Method Notes
				if((a.getClass()==Tag.class)) {
					System.out.print("method invoke:\t");
					mm.invoke(new Test(), 666);    //Call Method
				}
			}
		}
	}
	@Tag   //test method
	public void m(int n) {
		System.out.println("method m(int n): "+n);
	}
	@Tag2
	public void m(double n) {
		System.out.println("method m(double n): "+n);
	}
}
@Retention(RetentionPolicy.RUNTIME)   //Test Notes
@interface Tag{}
@Retention(RetentionPolicy.RUNTIME)
@interface Tag2{}

But the output of this program is not what I want to see, as shown below, and the invoke() method did not execute

Since the method m(int) marked by @Tag was not called, I used to view the output of the following statement

System.out.println("a.getClass()\t"+a.getClass());
System.out.println("Tag.class\t"+Tag.class);

 

Errors are quickly defined to the line if((a.getClass()==Tag.class)).A.getClass(), A is an example of the annotation we get by traversing the annotation collection (getAnnotations) of the Test.m() method.So a instanceof Annotation should be true.(tested, true)

On the other hand, we know that Annotation is a special Interface interface, so annotations cannot be instantiated.This printout, class test2.$Proxy1, makes sense (test2 is the current package name), that is, when the JVM calls getAnnotation, it automatically generates the @Tag annotated implementation class (anonymous class) and returns an instance of the class

 

In other words, can annotations also be implemented?

I typed the code in eclipse with a validated mind:

import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

public class Test4 {
	public static void main(String[] args) {
		Annotation annotation = new ttttt();
		System.out.println(annotation.getClass());
		System.out.println(annotation.annotationType());
	}
}
@Retention(RetentionPolicy.RUNTIME)
@interface Tag4{}

class ttttt implements Tag4{  //When implements Tag4 is written out, the @Override method is automatically prompted to be added
	@Override
	public Class<? extends Annotation> annotationType() {
		return Tag4.class;
	}
}

True as the above conjecture.

 

 

So go back to the original question.What should we do if getClass() is invalid if we want to call a method annotated by @Tag

In fact, the problem is much simpler. Knock annotation. Look at the tip and you know there is one way to do this: annotation Type ()

Change the code to:

for(Annotation a : mm.getAnnotations()) {
	if(a.annotationType()==Tag.class) {
		System.out.print("method invoke:\t");
		mm.invoke(new Test(), 666);
	}
}

 

 

 

 

11 original articles were published, 4 were praised, and 3133 were visited
Private letter follow

Posted by Brentley_11 on Mon, 20 Jan 2020 19:14:24 -0800