Heim > Java > javaLernprogramm > Hauptteil

Wie SpringBoot Reflektion verwendet, um IOC und getBean zu simulieren

王林
Freigeben: 2023-05-30 09:25:12
nach vorne
1010 Leute haben es durchsucht

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) und Weisen Sie W für andere Speicherbereiche außer dem Objektheader den Wert 0 zu.

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;
Nach dem Login kopieren

Werfen wir zunächst einen Blick auf die Funktionen dieser Methoden:

  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;
        }
    }
Nach dem Login kopieren

Beachten Sie, dass dies ein Konstrukt ohne Argumente ist Konstruktor ohne Argumente, es ist sehr nützlich, dass ein Fehler gemeldet wird, weil wir nicht wissen, wie viele Attribute er hat, oder? (Denken Sie immer daran, dass wir Reverse Engineering betreiben!!! Wir wissen nicht, was in diesem Typ ist !!!Alles sind Informationen, die durch Reflexion entstehen.)

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()));
        }
    }
Nach dem Login kopieren
# 🎜🎜#Holen Sie sich die Attribute und geben Sie die Attributwerte ein.

 public static Method[] getMethodArray(Object dataType) {
        return dataType.getClass().getDeclaredMethods();
    }
Nach dem Login kopieren

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);
        }
    }
Nach dem Login kopieren

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);
    }
Nach dem Login kopieren

Die Verwendungsmethode ist namentlich.

    @SneakyThrows
    public static Object getBean(Object dataType, Map<String, Object> parameterMap) {
        fillValueToNewInstance(dataType, parameterMap);
        fillMethodMap(dataType);
        return newInstance;
    }
Nach dem Login kopieren

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",&#39;女&#39;);
        Person bean = (Person) getBean(new Person(), map);
        System.out.println(bean.toString());
        System.out.println(useMethod("toString"));
    }
Nach dem Login kopieren

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=&#39;" + name + &#39;\&#39;&#39; +
                ", age=" + age +
                ", sex=" + sex +
                &#39;}&#39;;
    }
}
Nach dem Login kopieren

Die Testergebnisse lauten wie folgt:

Wie SpringBoot Reflektion verwendet, um IOC und getBean zu simulierenHier 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 Attributtyps

setAccessible(true) Richten Sie Brute-Force-Cracking ein und nutzen Sie private Attribute

getDeclaredMethods Holen Sie sich alle Methodenarrays

getClass Holen Sie sich die Bytecode-Datei

getConstructor 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!

Verwandte Etiketten:
Quelle:yisu.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!