Annotations and reflection for Java basics

Annotations and reflection are very much the underlying implementation of open source frameworks and the underlying logic is all through annotations and reflection.

1. The annotation

1.1 Introduction to annotations

Annotations are very important. The development model is now based on annotations, JPA is based on annotations, Spring is based on annotations, Hibernate is based on annotations, annotations are a new feature since JDK1.5.

Annotation is a kind of markup. Adding annotations to your program is tagging your program. If you don’t add annotations, you don’t have any markup at all. Just do the right thing. Tags can be added to packages, classes, properties, methods, method parameters, and local variables.

1.2 Built-in annotations

Three annotations provided internally since JDK1.5

@deprecated means “obsolete”.

Override means “overwrite”.

@SuppressWarnings means “Compression Warnings” and is used to SuppressWarnings produced by the compiler.

package com.njit.annotation; /** * @Author */ public class annotationTest {/** * @Param args * public class annotationTest {/** * @Args * Public static void main(String[] args) {sayHello(); public static void main(String[] args) {sayHello(); // The sayHello() method here has a line to indicate that this method is obsolete and is not recommended using @suppressWarnings ("unused") String STR = "SDFD "; } /** * This is also a built-in JDK annotation, meaning that this method has been deprecated, */ @Deprecated public static void SayHello () {System.out.println(" Hi, XXXX "); } /** * This is also an annotation provided internally after JDK1.5, * @return */ @override public String toString() {return "XXXX "; }}

1.3 Custom annotations, meta annotations

Yuan notes

Meta annotations are used to annotate other annotations. Java provides four standard meta-annotation types that are used to provide annotations to other annotation types.

These types and the classes they support are found in the java.lang.annotation package (@Target, @Retention,@Documented, @Inherited).

  • @target: Used to describe the scope of use of the annotation (i.e. where the annotation being described can be used)
  • @Retention: indicates at what level the annotation information needs to be retained, describing the annotation’s declaration period (SOURCE
  • @Documented: Indicates that the annotation is included in the Javadoc
  • @inherited: Indicates that subclasses inherit annotations from their parent class

Custom annotations

When using the @ interface custom annotations, automatic inherited Java. Lang. The annotation. The annotation interface.

  • @interfaceTo declare an annotation, in the format public @inteface annotation name {define content}
  • Each of these methods actually declares a configuration parameter.
  • The method name is the name of the parameter
  • The return value type is the type of the parameter (return values can only be primitive types, Class,String, enum).
  • Default can be used to declare the default value of a parameter
  • If there is only one parameter member, the general parameter is namedvalue
  • Annotation elements must have a value. When defining an annotation element, we often use an empty string with 0 as the default value
Public class Myanotation {// Annotations can display assignments, if there is no default value, @hello (name = "njit", age = 3) public void test() {}} /** * @author */ @target ({elementType.type, age, age, age, age) ElementType.method}) @Retention(RetentionPolicy.Runtime) @Interface Hello{// Arguments for annotation: Arguments type + Arguments name (); String name() default ""; int age(); }

1.4 Real world usage scenarios for custom annotations

  • Scenario description: Use the SpringBoot interceptor to implement a feature that prompts the user that the interface needs to be logged in to access if @LoginRequired is added to the method, otherwise no login is required
@Target(elementType.method) @Retention(RetentionPolicy.Runtime) public @Interface LoginRequired {} //2. @RestController public class IndexController {@getMapping ("/sourceA") public String sourceA(){return "You are accessing the Sourcea resource "; } @getMapping ("/sourceB") public String sourceB(){return "You are using sourceB"; }} // 3. The test now accesses both interfaces successfully // 4. Custom interceptors, Public class SourceAccessInterceptor implements HandlerInterceptor {@Override public Boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {System.out.println(); HandlerMethod handlerMethod = (HandlerMethod)handler; LoginRequired loginRequired = handlerMethod.getMethod().getAnnotation(LoginRequired.class); if(loginRequired == null){ return true; } // There is a LoginRequired annotation that says login is required, prompting the user to log in Response. setContentType("application/json; charset=utf-8"); Response.getWriter ().print(" The resource you access needs to be logged in "); return false; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } } // 5. Implement the Spring class WebMVCConfigurer, Create a Configuration class add interceptors to interceptor in the chain @ Configuration public class InterceptorTrainConfigurer implements WebMvcConfigurer {@ Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new SourceAccessInterceptor()).addPathPatterns("/**"); }} // @RestController public class IndexController {@GetMapping("/sourceA") public String @RestController public class IndexController {@GetMapping("/sourceA") public String SourceA (){return "You are accessing sourceA resources "; } @loginRequired @getMapping ("/sourceB") public String sourceB(){return "You are accessing sourceB resources "; }} //7. Verify that access to interface B will be blocked

2. The reflection

The main API for reflection

A simple case of reflection

package com.njit.reflection; /** * @Author: njitzyd * @Date: 2020/11/22 18:53 * @Description: // public class Test01 {public static void main(String[] args) throws ClassNotFoundException {// Class c1 = class.forName (" com.njit.reflect.user "); Class c2 = Class.forName("com.njit.reflection.User"); Class c3 = Class.forName("com.njit.reflection.User"); // When a Class is loaded, the entire structure of the Class is encapsulated in the Class object; System.out.println(C1.hashCode ()); System.out.println(c2.hashCode()); System.out.println(c3.hashCode()); }} /** ** class User {private String Name; private int id; private int age; public User() { } public User(String name, int id, int age) { this.name = name; this.id = id; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "User{" + "name='" + name + '\'' + ", id=" + id + ", age=" + age + '}'; }}

Class Class

As you can see from the figure above, a Class can only have one Class object.

Several ways to get the Class Class

Gets a code demo of the Class Class

package com.njit.reflection; /** * @Author: njitzyd * @Date: 2020/11/22 20:28 * @Description: * @version 1.0.0 */ public Class Test02 {public static void main(String[] args) throws ClassNotFoundException { Person person = new Student(); System.out.println(" This person is: "+ Person.getName ()); Class C1 = Person.getClass (); System.out.println(c1.hashCode()); 2: / / way by class.forname () to obtain a Class c2 = Class. Class.forname (" com. Njit. Reflection. Student "); System.out.println(c2.hashCode()); Class c3 = Student. Class; Class c3 = Student. Class; System.out.println(c3.hashCode()); Class c4 = Integer.type; Class c4 = Integer.type; Class c4 = Integer.type; System.out.println(c4); // getSuperClass = C1.getSuperClass (); System.out.println(c5.hashCode()); } } class Person{ private String name; public Person() { } public Person(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Person{" + "name='" + name + '\'' + '}'; } class Student extends Person{public Student() {super(" Student "); }} class Teacher extends Person{public Teacher() {super(" Teacher "); }}

Which classes can have Class objects (followed by some examples)

  • Class: external class, member (member inner class, static inner class), local inner class, anonymous inner class
  • Interface: Comparable. Class
  • [] : array (String []. Class)
  • Enum: Enumeration (elementType.class)
  • Annotation: Annotation @Interface (Override. Class)
  • Primitive type: primitive data type (Integer.class, Int.class)
  • void (void.class)

Class loading

The loading process of the class

When does class initialization occur

The first passive reference above is that when a static variable of a parent class is called from a child class, such as (son.b), note that the Son class is a class, not an object.

(int Son[] array = new Son[5]); (int Son[] array = new Son[5]); (int Son[] array = new Son[5]);

Third, if it is a static final constant, initialization will not be triggered.

What class loaders do

package com.njit.reflection; /** * @Author: njitzyd * @Date: 2020/11/22 22:01 * @Description: Test03 * @version 1.0.0 */ public class Test03 {public static void main(String[] args) throws ClassNotFoundException { / / acquisition system class loader this systemClassLoader. = this getSystemClassLoader (); System.out.println(systemClassLoader); / / the system class loader for the parent class loader - > extension class loader this parent. = systemClassLoader getParent (); System.out.println(parent); }}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}}} System.out.println(parent1); / / test the current Class Class loader this this = Class. Class.forname (" com. Njit. Reflection. Test03 "). The getClassLoader (); System.out.println(classLoader); ClassLoader = class.forName ("java.lang.Object").getClassLoader(); classLoader = class.forName ("java.lang.Object").getClassLoader(); System.out.println(commonClassLoader); System.out.println(System.getProperty("java.class.path")); System.getProperty("java.class. }}

Parental delegation mechanism

Parent delegation means that if a class loader needs to load a class, it will first delegate the class request to the parent class loader to do so, at every level. It recurses all the way to the top level, and when the parent loader is unable to complete the request, the subclass attempts to load.

Parental delegate mechanism reference

Gets the runtime structure of the class

import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; /** * @Author: njitzyd * @Date: 2020/11/23 20:27 * @Description: Test04 * @version 1.0.0 */ public class Test04 {public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, NoSuchMethodException { Class c1 = Class.forName("com.njit.reflection.User"); System.out.println(C1. GetName ()); System.out.println(C1. System.out.println(C1. GetSimpleName ()); Public Field[] Fields = C1.getFields (); public Field[] Fields = C1.getFields (); GetDeclaredFields = C1.getDeclaredFields (); for (Field field : fields) { System.out.println(field); } Field name = c1. GetDeclaredField (" Name "); System.out.println(name); Public Method[] methods = C1.getMethods (); public Method[] methods = C1. For (Method: methods) {System.out.println(" normal Method: "+ Method); } // Get all methods of this class, including private methods = C1.getDeclaredMethods (); For (Method: methods) {System.out.println(" Get all methods of this class: "+ Method); } Method getName = C1. GetMethod ("getName", null);} Method getName = C1. System.out.println(getName); Method setName = c1.getMethod("setName", String.class); System.out.println(setName); // Constructor[] Constructors = C1. Constructors(); for (Constructor constructor : constructors) { System.out.println(constructor); } constructors = c1.getDeclaredConstructors(); for (Constructor constructor : constructors) { System.out.println(constructor); } / / for specified Constructor Constructor Constructor = c1. GetDeclaredConstructor (String class, int. J class, int. J class); System.out.println(constructor); }}

Dynamically create object execution methods

Performance analysis

package com.njit.reflection; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** * @Author: njitzyd * @Date: 2020/11/24 22:06 * @Description: Public static void test01(){User User = new User(); public static void test01(){User User = new User(); long startTime = System.currentTimeMillis(); for (int i = 0; i < 10_0000_0000; i++) { user.getName(); } long endTime = System.currentTimeMillis(); System.out.println(" 1 billion times in normal mode :"+(endTime-startTime)+"ms"); } / reflection way * * * * / public static void test02 () throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { User user = new User(); Class c1 = user.getClass(); Method getName = c1.getMethod("getName", null); long startTime = System.currentTimeMillis(); for (int i = 0; i < 10_0000_0000; i++) { getName.invoke(user, null); } long endTime = System.currentTimeMillis(); System.out.println(" 1 billion reflections executed :"+(endTime-startTime)+"ms"); } /** * / * @throws NoSuchMethodException */ public static void test03() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { User user = new User(); Class c1 = user.getClass(); Method getName = c1.getMethod("getName", null); getName.setAccessible(true); long startTime = System.currentTimeMillis(); for (int i = 0; i < 10_0000_0000; i++) { getName.invoke(user, null); } long endTime = System.currentTimeMillis(); System.out.println(" Check off by reflection ":"+(endTime-startTime)+"ms"); } public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException { test01(); test02(); test03(); }} # # # # # # # # # # # # # # # # # # # # ordinary way perform 1 billion times: 3 ms reflection way perform 1 billion times: 1454 ms reflection pattern close test performed 1 billion times: 977 ms

Reflection manipulation generics

package com.njit.reflection; import java.lang.reflect.Method; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.List; import java.util.Map; /** * @Author: njitzyd * @Date: 2020/11/24 22:15 * @Description: * @version 1.0.0 */ public class Test07 {public static void test01(Map<String, User> Map, User> Map, List<Integer> list){ System.out.println("test01"); } public static Map<Long, User> test02(){ System.out.println("test02"); return null; } public static void main(String[] args) throws NoSuchMethodException { Method method = Test07.class.getMethod("test01",  Map.class, List.class); Type[] genericParameterTypes = method.getGenericParameterTypes(); for (Type genericParameterType : genericParameterTypes) { System.out.println("###"+genericParameterType); if (genericParameterType instanceof ParameterizedType){ Type[] actualTypeArguments = ((ParameterizedType) genericParameterType).getActualTypeArguments(); for (Type actualTypeArgument : actualTypeArguments) { System.out.println(actualTypeArgument); } } } method = Test07.class.getMethod("test02", null); Type returnType = method.getGenericReturnType(); if (returnType instanceof ParameterizedType){ Type[] actualTypeArguments = ((ParameterizedType) returnType).getActualTypeArguments(); for (Type actualTypeArgument : actualTypeArguments) { System.out.println(actualTypeArgument); } } } } ########## ###java.util.Map<java.lang.String, com.njit.reflection.User> class java.lang.String class com.njit.reflection.User ###java.util.List<java.lang.Integer> class java.lang.Integer class java.lang.Long class com.njit.reflection.User

The following figure as understood

Reflection operation annotation

package com.njit.reflection; import java.lang.annotation.*; import java.lang.reflect.Field; /** * @Author: njitzyd * @Date: 2020/11/24 22:30 * @Description: * @version 1.0.0 */ public class Test08 {public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException { Class c1 = Class.forName("com.njit.reflection.Animal"); // Annotation[] annotations = C1. Getannotations (); System.out.println(annotations); MyTest = (myTest) c1.getAnnotation(myTest.class); myTest = (myTest) c1.getAnnotation(myTest.class); System.out.println(myTest.value()); Field Field = c1. GetDeclaredField (" Name "); FieldTest annotation = field.getAnnotation(FieldTest.class); System.out.println(annotation.columnName()); System.out.println(annotation.type()); System.out.println(annotation.length()); } } @MyTest("db_test") class Animal{ @FieldTest(columnName = "id", type = "Integer", length = 10) private int id; @FieldTest(columnName = "age", type = "Integer", length = 8) private int age; @FieldTest(columnName = "name", type = "String", length = 10) private String name; public Animal() { } public Animal(int id, int age, String name) { this.id = id; this.age = age; this.name = name; } public int getId() { return id; } public void setId(int id) { this.id = id; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return "Animal{" + "id=" + id + ", age=" + age + ", name='" + name + '\'' + '}'; }} /** * Custom simple annotations, */ @Target(ElementType.type) @Retention(RetentionPolicy.Runtime) @Interface myTest {String value(); } /** * Custom simple annotations, */ @Target(ElementType.Field) @Retention(RetentionPolicy.Runtime) @Interface FieldTest{String columnName(); String type(); int length(); }