How does java annotation annotation use and reflection get annotations
- 2020-05-30 20:06:15
- OfStack
1. Annotate the basics
1. Meta notes
Meta-annotations are annotations of annotations. Including @Retention @Target @Document @Inherited4.
1. Type Annotation is defined as @interface. All Annotation automatically inherit the java.lang.Annotation interface and cannot inherit other classes or interfaces.
2. Parameter members can only be decorated with the two access rights public or the default (default)
3. Members can only use basic types byte parameters, short, char, int, long, float, double, boolean8 basic data types and String, Enum, Class, annotations, such as data types, and the 1 some type of the array.
4. To get annotation information for class methods and fields, you must use Java's reflection technique to get Annotation objects, because you have no other way to get annotation objects
5. Annotations can also have no members defined, but they are useless
When defining a custom annotation class, you can specify the target (class, method, field, constructor, etc.), the lifecycle of the annotation (valid at runtime in class files or source code), whether to include the annotation in javadoc, and whether to allow subclasses to inherit the annotation from the parent class, as follows:
1. @Target represents the annotation target, and possible ElemenetType parameters include:
ElemenetType.CONSTRUCTOR Constructor declaration
ElemenetType.FIELD The domain statement ( including enum The instance )
ElemenetType.LOCAL_VARIABLE Local variable declaration
ElemenetType.METHOD Method statement
ElemenetType.PACKAGE Package declaration
ElemenetType.PARAMETER Parameter declarations
ElemenetType.TYPE Classes and interfaces ( Including annotation types ) or enum The statement
2. @Retention indicates the lifecycle of the annotation, and the optional RetentionPolicy parameters include
RetentionPolicy.SOURCE Annotations are discarded by the compiler
RetentionPolicy.CLASS Annotations in class Available in file, but will be VM discarded
RetentionPolicy.RUNTIME VM Annotations are also retained at run time, so they can be read through a reflection mechanism
3. @Documented indicates that this annotation is included in javadoc
4. The @Inherited directive allows subclasses to inherit annotations from their parent classes
2. How is it used in java
2.1. Define annotations
package com.test.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
public class MyAnnotation {
/**
* Annotation class
* @author T4980D
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface MyClassAnnotation {
String uri();
String desc();
}
/**
* Construction annotation
* @author T4980D
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.CONSTRUCTOR)
public @interface MyConstructorAnnotation {
String uri();
String desc();
}
/**
* My method notes
* @author Owner
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyMethodAnnotation {
String uri();
String desc();
}
/**
* Field annotation definition
* @author Owner
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface MyFieldAnnotation {
String uri();
String desc();
}
/**
*
* You can apply to both classes and methods
* @author T4980D
*
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface Yts {
// Define the enumeration
public enum YtsType {
util, entity, service, model
}
// Set default values
public YtsType classType() default YtsType.util;
// An array of
int[] arr() default {3, 7, 5};
String color() default "blue";
}
}
2.2 basic test notes
package com.test.annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import com.test.annotation.MyAnnotation.MyClassAnnotation;
import com.test.annotation.MyAnnotation.MyConstructorAnnotation;
import com.test.annotation.MyAnnotation.MyFieldAnnotation;
import com.test.annotation.MyAnnotation.MyMethodAnnotation;
import com.test.annotation.MyAnnotation.Yts;
import com.test.annotation.MyAnnotation.Yts.YtsType;
@MyClassAnnotation(desc = "The class", uri = "com.test.annotation.Test")
@Yts(classType =YtsType.util)
public class TestAnnotation {
@MyFieldAnnotation(desc = "The class field", uri = "com.test.annotation.Test#id")
private String id;
@MyConstructorAnnotation(desc = "The class constructor", uri = "com.test.annotation.Test#MySample")
public TestAnnotation() {
}
public String getId() {
return id;
}
@MyMethodAnnotation(desc = "The class method", uri = "com.test.annotation.Test#setId")
public void setId(String id) {
System.out.println(" method info: "+id);
this.id = id;
}
@MyMethodAnnotation(desc = "The class method sayHello", uri = "com.test.annotation.Test#sayHello")
@Yts
public void sayHello(String name){
if(name == null || name.equals("")){
System.out.println("hello world!");
}else{
System.out.println(name + "\t:say hello world!");
}
}
public static void main(String[] args) throws Exception {
Class<TestAnnotation> clazz = TestAnnotation.class;
// Get class annotations
MyClassAnnotation myClassAnnotation = clazz.getAnnotation(MyClassAnnotation.class);
System.out.println(myClassAnnotation.desc() + " "+ myClassAnnotation.uri());
// Get the constructor annotation
Constructor<TestAnnotation> cons = clazz.getConstructor(new Class[]{});
MyConstructorAnnotation myConstructorAnnotation = cons.getAnnotation(MyConstructorAnnotation.class);
System.out.println(myConstructorAnnotation.desc() + " "+ myConstructorAnnotation.uri());
// Get method annotation
Method method = clazz.getMethod("setId", new Class[]{int.class});
MyMethodAnnotation myMethodAnnotation = method.getAnnotation(MyMethodAnnotation.class);
System.out.println(myMethodAnnotation.desc() + " "+ myMethodAnnotation.uri());
// Get field annotations
Field field = clazz.getDeclaredField("id");
MyFieldAnnotation myFieldAnnotation = field.getAnnotation(MyFieldAnnotation.class);
System.out.println(myFieldAnnotation.desc() + " "+ myFieldAnnotation.uri());
}
}
2.3 analysis by reflection
package com.test.annotation;
import java.lang.reflect.Method;
import java.util.Arrays;
import com.test.annotation.MyAnnotation.MyClassAnnotation;
import com.test.annotation.MyAnnotation.MyMethodAnnotation;
import com.test.annotation.MyAnnotation.Yts;
import com.test.annotation.MyAnnotation.Yts.YtsType;
public class ParseAnnotation {
/**
* Parsing method annotation
* @param <T>
* @param clazz
*/
public static <T> void parseMethod(Class<T> clazz) {
try {
T obj = clazz.newInstance();
for (Method method : clazz.getDeclaredMethods()) {
MyMethodAnnotation methodAnnotation = method.getAnnotation(MyMethodAnnotation.class);
if (methodAnnotation!=null) {
// The method with this annotation is called by reflection
method.invoke(obj, methodAnnotation.uri());
}
Yts yts = (Yts) method.getAnnotation(Yts.class);
if (yts != null) {
if (YtsType.util.equals(yts.classType())) {
System.out.println("this is a util method");
} else {
System.out.println("this is a other method");
}
System.out.println(Arrays.toString(yts.arr())); // Print the array
System.out.println(yts.color()); // The output color
}
System.out.println("\t\t-----------------------");
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* Parse class annotation
* @param <T>
* @param clazz
*/
public static <T> void parseType(Class<T> clazz) {
try {
Yts yts = (Yts) clazz.getAnnotation(Yts.class);
if (yts != null) {
if (YtsType.util.equals(yts.classType())) {
System.out.println("this is a util class");
} else {
System.out.println("this is a other class");
}
}
MyClassAnnotation classAnnotation = (MyClassAnnotation) clazz.getAnnotation(MyClassAnnotation.class);
if (classAnnotation != null) {
System.err.println(" class info: "+classAnnotation.uri());
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
parseMethod(TestAnnotation.class);
parseType(TestAnnotation.class);
}
}
3. Annotate application cases
3.1 regarding fine-grained authority interception, any of the 11 action methods can be intercepted according to the authority of the login user in Struts2, and a custom method annotation can be defined, for example
@Retention(RetentionPolicy.RUNTIME)// On behalf of Permission The comment remains in the stage
@Target(ElementType.METHOD)// Labeled above the method
public @interface Permission {
/** The module */
String module();
/** Permission values */
String privilege();
}
3, 2 for example, there is a department action, Department. action, there is a method public String departmentlistUI(){} can be defined in this way
@Permission(module="department",privilege="view")
public String departmentlistUI(){
}
3.3. Then define a permission interceptor PrivilegeInterceptor.java and register it in struts.xml. After the implementation of interceptor interface, the implementation method public String intercept(ActionInvocation invocation) throws Exception {}. This code gets the action name and method name.
String actionName=invocation.getProxy().getActionName();
String methodName=invocation.getProxy().getMethod();
System.out.println(" Intercepted: action Name: "+actionName+" The method name: "+methodName);
4. Then, through reflection technology, get the custom permission annotation on this method, get the user who is currently logged in (from session), traverse the permission group owned by the current user, and traverse all the permissions under any one permission group to see whether the required permissions for annotation on this method are included. This allows fine-grained interception of action method permissions.
private boolean validate(ActionInvocation invocation) throws SecurityException, NoSuchMethodException {
String methodName=invocation.getProxy().getMethod();
Method currentMethod = invocation.getAction().getClass().getMethod(methodName);
if(currentMethod != null && currentMethod.isAnnotationPresent(Permission.class)){
// Get a comment on the method
Permission permission = currentMethod.getAnnotation(Permission.class);
// The required permissions on this method
SystemPrivilege methodPrivilege = new SystemPrivilege(new SystemPrivilegePK(permission.module(), permission.privilege()));
// Gets the user currently logged in
Employee e = (Employee) ActionContext.getContext().getSession().get("loginUser");
// Traverses all permission groups under the current user
for(PrivilegeGroup group : e.getGroups()){
// If the permission group contains the permissions needed to access the method, release it
if(group.getPrivileges().contains(methodPrivilege)){
return true;
}
}
// Indicates that the traversal of all the permission groups of the user, the permission was not found, indicating that the permission is not available
return false;
}
// There is no annotation to indicate that anyone can call the method
return true;
}
Thank you for reading, I hope to help you, thank you for your support of this site!