Spring-Grundidee IOC
Der zweite ist die Java-Reflexion. Der Reflexionsmechanismus ist heute ein wichtiger Implementierungskern von Spring, als ich mir den Cache der dritten Ebene ansah, um das Problem zu lösen Zirkelverweise: Der Lebenszyklus von Java-Objekten ist dem Generierungsprozess von Java-Objekten sehr ähnlich. Dann habe ich festgestellt, dass der Prozess der Bean-Instanz von Grund auf sehr interessant ist Extrem eleganter Code zur Realisierung der Verwendung von Reflection und verschiedener Kartendatenstrukturen zur Realisierung der Pipeline-Produktion von Beans, was sehr elegant ist. Deshalb habe ich versucht, Reflektion zu verwenden, um ein Gadget zu schreiben, das Instanzobjekte umgekehrt generiert.
Dann müssen Sie den Prozess der Objektgenerierung im Voraus kennen:
Ich fasse den Objekterstellungsprozess wie folgt zusammen:
Überprüfen Sie, ob der konstante Pool vorhanden ist existiert Die symbolische Referenz des Objekts wird verwendet, um festzustellen, ob es den Klassenladevorgang durchlaufen hat. Wenn nicht, wird der Klassenladevorgang ausgeführt.
Speicher für neue Objekte zuweisen (zwei Methoden: Zeigerkollision und freie Liste
Legen Sie den Objektheader fest.
Objektinitialisierung. Dabei handelt es sich um den Prozess der Ausführung Ihrer Konstruktormethode und der Zuweisung der Werte, die Sie definieren möchten, zu den benötigten Feldern.
Fügen Sie die Details hinzu: Beim Zuweisen von Speicher für neue Objekte wird zunächst die Speichergröße, die ein Objekt nach Abschluss des Ladens der Klasse benötigt, vollständig bestimmt Teilen Sie in Java ein gleich großes Stück Speicher im Heap auf, aber wie teilt man es auf? Wenn das Speicherlayout des Java-Heaps in einer strengen Reihenfolge zugewiesen wird, dh eine Seite verwendet wird und die andere Seite frei ist, wird der Speicher durch Zeigerkollision zugewiesen. Der sogenannte Zeiger wird an der Trennlinie gesammelt zwischen dem freien Bereich und dem genutzten Bereich bewegt sich der Zeiger rückwärts, bis die von der Verschiebung zurückgelegte Länge der vom Java-Objekt benötigten Speichergröße entspricht, und stoppt und reserviert. Was aber, wenn das Speicherlayout des Java-Heaps fragmentiert und diskontinuierlich ist? Wir können nur eine Liste verwalten, in der die Größen- und Standortinformationen aller freien Java-Heap-Bereiche aufgezeichnet werden. Bei der Zuweisung müssen wir nur die am besten geeignete Bereichszuordnung für neue Objekte finden.
Die Fähigkeit des Garbage Collectors und ob er Speicherplatzkomprimierung und -sortierung durchführen kann, bestimmen, ob der Java-Heap regelmäßig ist. Wenn die von uns verwendeten Kollektoren Serial und Parnew sind, werden sie durch Zeigerkollision zugewiesen. Wenn wir den CMS-Garbage Collector verwenden, müssen wir die problematische Zuweisung von freien Bereichstabellen verwenden.
Hier konzentrieren wir uns auf das Ausfüllen von Attributen und Methoden: Die Seele eines Objekts sind seine Attribute und Methoden:
Die vom gesamten Tool verwendeten Kernattribute: # 🎜🎜#
private static volatile Constructor<?> constructor; private static volatile Object newInstance; private static volatile Map<String, Method> methodMap;
public static Constructor<?> getConstructor(Object dataType) { Class<?> typeClass = dataType.getClass(); try { Constructor<?> constructor = typeClass.getConstructor(); constructor.setAccessible(true); return constructor; } catch (NoSuchMethodException e) { e.printStackTrace(); return null; } }
public static void fillValueToNewInstance(Object dataType, Map<String, Object> initialMap) throws Exception { constructor = getConstructor(dataType); Class<?> typeClass = dataType.getClass(); Field[] declaredFields = typeClass.getDeclaredFields(); Iterator<Field> fieldIterator = Arrays.stream(declaredFields).iterator(); newInstance = constructor.newInstance(); while (fieldIterator.hasNext()) { Field field = fieldIterator.next(); field.setAccessible(true); if (initialMap != null) field.set(newInstance, initialMap.get(field.getName())); } }
public static Method[] getMethodArray(Object dataType) { return dataType.getClass().getDeclaredMethods(); }
Alle Methoden abrufen, um ein Methodenarray zu bilden.
public static void fillMethodMap(Object dataType) { methodMap = new HashMap<>(); Method[] methodArray = getMethodArray(dataType); Iterator<Method> iterator = Arrays.stream(methodArray).iterator(); while (iterator.hasNext()) { Method method = iterator.next(); method.setAccessible(true); methodMap.put(method.getName(), method); } }
Speichern Sie die Methode zur Speicherung in der Methodensammlung.
public static Object useMethod(String methodName, @Nullable Object... parameters) throws Exception { return methodMap.get(methodName).invoke(newInstance, parameters); }
Die Verwendungsmethode ist namentlich.
@SneakyThrows public static Object getBean(Object dataType, Map<String, Object> parameterMap) { fillValueToNewInstance(dataType, parameterMap); fillMethodMap(dataType); return newInstance; }
getBean-Methode.
public static void main(String[] args) throws Exception { Map<String,Object> map = new HashMap<>(); map.put("name","xu"); map.put("age",Integer.valueOf(18)); map.put("sex",'女'); Person bean = (Person) getBean(new Person(), map); System.out.println(bean.toString()); System.out.println(useMethod("toString")); }
Testmethode. Die Typinformationen lauten wie folgt:
class Person { private String name; private Integer age; private Character sex; //无参构造绝对不能少 public Person() { } @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + ", sex=" + sex + '}'; } }
Die Testergebnisse lauten wie folgt:
Hier verwenden wir nicht Person Person = new Person(); Das Objekt wird mittels Reflektion instanziiert.
Ich liste die darin verwendeten Reflexionsmethoden auf:
getDeclaredFields Holen Sie sich das Domänenattributobjekt
getName Holen Sie sich den Attributnamen
#🎜 🎜#getType Holen Sie sich die Bytecode-Datei des AttributtypssetAccessible(true) Richten Sie Brute-Force-Cracking ein und nutzen Sie private AttributegetDeclaredMethods Holen Sie sich alle MethodenarraysgetClass Holen Sie sich die Bytecode-DateigetConstructor Holen Sie sich den Konstruktor ohne Argumente
Das obige ist der detaillierte Inhalt vonWie SpringBoot Reflektion verwendet, um IOC und getBean zu simulieren. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!