Reflection overview: reflection is the soul of the frame!
1.1 JAVA reflection mechanism
In the running state, you can know all the properties and methods of any class; For any object, you can call any of its methods and properties; This function of dynamically obtaining information and dynamically calling object methods is called the reflection mechanism of java language.
You can get all the byte codes in the object class.
(class information: class name, package name, attribute, construction method, common method, inherited method)
p = new People();
ApplocationContext context = new ClassPathXmlApplocationContext("bean.xml");
context.getBean("id"); context.getBean(People.class); context.getBean("id",People.class);
reflection:
1. How to get the bytecode object of class? 2. How to obtain information in a class through bytecode objects? 3. How to use the information in the obtained object?
Now you need to use reflection!!!
Steps:
1. Get the bytecode object of the class 2.Extract information from class 3. Use class information
1.2 use of reflection
Java reflection mechanism to obtain class information is actually to obtain the contents of the bytecode file of the class and encapsulate these contents into a bytecode object, so we only need to use the reflected code to obtain the bytecode object to get the class information.
1.2.1 Class introduction
Class represents the entity of the class and represents the class and interface in the running Java application. There are many useful methods in this class. Here is a brief introduction to their classification.
-
Methods for obtaining Class related information
Class.forName(""Full class name"); object.getClass(); Class name.class;
-
Basic methods for obtaining information of classes:
Method name meaning getName() Get the full path name of the class newInstance() Create an instance of a class getPackage() Get the package of the class getSimpleName() Get the name of the class getSuperclass() Gets the name of the parent class that the current class inherits getInterfaces() Get the class or interface implemented by the current class -
Get the methods related to the properties in the class
Method name meaning getField(String name) Get a public property object getFields() Get all public property objects getDeclaredField(String name) Get a property object getDeclaredFields() Get all attribute objects -
Get the annotation related methods in the class
Method name meaning getAnnotation(Class annotationClass) Returns the public annotation object in this class that matches the parameter type getAnnotations() Returns all public annotation objects of this class getDeclaredAnnotation(Class annotationClass) Returns all annotation objects in this class that match the parameter type getDeclaredAnnotations() Returns all annotation objects of this class -
Get constructor related methods in the class
Method name meaning getConstructor(Class...<?> parameterTypes) Get the public constructor matching the parameter type in this class getConstructors() Get all public constructors of this class getDeclaredConstructor(Class...<?> parameterTypes) Get the constructor matching the parameter type in this class getDeclaredConstructors() Get all construction methods of this class -
Get the methods related to the methods in the class
Method name | meaning |
---|---|
getMethod(String name, Class<?>... parameterTypes) | Get a public method of this class |
getMethods() | Get all public methods of this class |
getDeclaredMethod(String name, Class<?>... parameterTypes) | Get a method of this class |
getDeclaredMethods() | Get all methods of this class |
1.2.2 get bytecode objects of classes - three methods
-
Get according to the full class name of the class
Class.forName("Full class name");
-
Get bytecode object by class name
Class name.class
-
Get bytecode object through instance object of class
Class name variable name = new Class name(); Variable name.getClass();
public static void main(String[] args) throws Exception { //Three ways //1.Class.forName("full class name"); Gets the bytecode object of the class through the class path Class pClass1 = Class.forName("com.aaa.reflex.demo1.People"); System.out.println(pClass1); //2. Class name class Class pClass2 = People.class; System.out.println(pClass2); //3. Pass the object getClass(); People people = new People(); Class pClass3 = people.getClass(); System.out.println(pClass3); System.out.println(pClass1 == pClass2); System.out.println(pClass1 == pClass3); }
**Note: * * the bytecode objects of the classes obtained by the three methods are the same.
1.2.3 obtain the class information according to the bytecode object of the class and use it.
-
Gets and calls the constructor of the class
public void test1() throws Exception { //1. Get bytecode object of class Class pClass = People.class; //2. Obtain the construction information in the bytecode object Constructor constructor = pClass.getConstructor(int.class); System.out.println(constructor); //The instance object is created by calling the newInstance method through the constructor obtained from the bytecode object of the class and passing in the required parameters People o = (People) constructor.newInstance(5); System.out.println(o); Constructor constructor1 = pClass.getConstructor(int.class, String.class); System.out.println(constructor1); Constructor constructor2 = pClass.getConstructor(int.class, String.class, String.class); System.out.println(constructor2); //The instance object is created by calling the newInstance method through the constructor obtained from the bytecode object of the class and passing in the required parameters Object o1 = constructor2.newInstance(18, "Zhang San", "male"); System.out.println(o1); //Get all public constructs Constructor[] constructors = pClass.getConstructors(); System.out.println(Arrays.toString(constructors)); //Get constructor without considering the modifier of construction //Single Constructor declaredConstructor = pClass.getDeclaredConstructor(String.class, String.class); System.out.println(declaredConstructor); //Get all constructors Constructor[] declaredConstructors = pClass.getDeclaredConstructors(); System.out.println(Arrays.toString(declaredConstructors)); //pClass.newInstance(); By default, the null construction method without parameters is called Object o2 = pClass.newInstance(); System.out.println(o2); }
Note: the code bytecode object is used directly without obtaining the null structure without parameters newInstance(); The null structure without parameters is called by default.
-
Get and call the properties of the class
Field class: field represents the member variable of the class (also known as the attribute of the class).
method meaning get(Object obj) Get the corresponding attribute value in obj set(Object obj, Object value) Set the corresponding attribute value in obj setAccessible(boolean b) Ignore the permission modifier. If the member variable is private, it needs to be turned on public void test2() throws Exception{ //1. Get bytecode object of class Class pClass = People.class; //2. Get the attribute information in the class // The Field class provides information about some operation properties //Get the variable / attribute of pulic modifier Field age = pClass.getField("age"); System.out.println(age); Object o = pClass.newInstance(); /* The object parameter obj needs to be passed in the set(Object obj,value) method to assign a value to the attribute obj : The attribute object parameter of which class this attribute is passed into the instance object of which class */ age.set(o,18); System.out.println(o); //Get the properties of all Public modifiers Field[] fields = pClass.getFields(); System.out.println(Arrays.toString(fields)); /** * Get properties without considering modifiers */ //single Field name = pClass.getDeclaredField("name"); Object o1 = pClass.newInstance(); //Ignore the permission modifier. Originally, the name attribute is private and cannot be assigned directly. setAccessible(true) must be turned on before assignment name.setAccessible(true); name.set(o1,"Zhang San"); System.out.println(o1); //All Field[] declaredFields = pClass.getDeclaredFields(); System.out.println(Arrays.toString(declaredFields)); }
-
Get and call the normal method of the class
The Method class represents the Method of the class
method purpose invoke(Object obj, Object... args) Pass the object object and parameters and call the method corresponding to the object public void test3()throws Exception{ //1. Get bytecode object of class Class pClass = People.class; //2. Get the method information in the class //Gets a method without parameters Method aaa = pClass.getMethod("aaa"); System.out.println(aaa); //invoke(Object obj, Object... args) calls this method through the invoKe method aaa.invoke(pClass.newInstance());//Call aaa() method //Get methods with parameters Method aaa1 = pClass.getMethod("aaa", int.class); System.out.println(aaa1); aaa1.invoke(pClass.newInstance(),6); /* The access method of permission modifier is not considered */ //Get a single, according to the method name and parameter type Method bbb = pClass.getDeclaredMethod("bbb", int.class); System.out.println(bbb); //Get all Method[] methods = pClass.getDeclaredMethods(); System.out.println(Arrays.toString(methods)); }
-
Get annotation information
/** * Get annotation information */ @Test public void test4() throws Exception{ //1. Get bytecode object of class Class<People> pClass = People.class; //2. Get the information of annotation //Get annotation object Annotation annotation1 = pClass.getAnnotation(MyAnno.class); System.out.println(annotation1); //Force the Annotation object of Annotation type into the subclass type we use MyAnno myanno = (MyAnno) pClass.getAnnotation(MyAnno.class); System.out.println(myanno); System.out.println(myanno.value()); }
Note: if you want to retrieve the value set in the Annotation, you need to forcibly convert the obtained Annotation object into the Annotation object you use
1.2.4 reflection cases
(1) Create a custom annotation (used to get the attribute value of the annotation attribute)
//Specify the scope of use of annotations @Target({ElementType.FIELD,ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface FieldName { String value(); }
(2) Create an entity class and add annotations
@TableName("book") public class Book { @FieldName("bookid") private Integer id; @FieldName("bookname") private String bookname; @FieldName("typeid") private Integer typeid; @FieldName("author") private String author; }
(3) Use the reflection mechanism to get the Book object and splice its properties into an aql query statement
public class SelectSql { /** * Main function * */ public static void main(String[] args) throws Exception{ //Get the query statement of book String sql = getSql(Book.class); System.out.println(sql); } /** * Customize a static method to obtain the method of query statement, and pass in the bytecode of the entity class to be obtained * */ public static String getSql(Class c){ //1. Get bytecode object of entity class Class bookClass = c; //Class<?> bookClass = Class.forName("com.aaa.reflex.demo2.User"); //2. Extract annotation information from entity class //2.1 extract table name TableName tableName =(TableName) bookClass.getAnnotation(TableName.class); System.out.println(tableName.value()); //2.2 extract field name Field[] fields = bookClass.getDeclaredFields(); //System.out.println(Arrays.toString(fields)); //Create a list to store all field names ArrayList<String> strings = new ArrayList<>(); for (int i = 0; i < fields.length; i++) { FieldName fieldName = fields[i].getAnnotation(FieldName.class); strings.add(fieldName.value()); } System.out.println(strings); //3. Process the extracted table name and field name into the sql statement we need StringBuffer sql = new StringBuffer("select "); for (int i = 0; i < strings.size(); i++) { if(i<strings.size()-1){ sql.append(strings.get(i)+","); }else{ sql.append(strings.get(i)+" "); } } sql.append("from "+tableName.value()); //System.out.println(sql); return sql.toString(); } }