Maison > Java > javaDidacticiel > le corps du texte

Comment SpringBoot utilise la réflexion pour simuler IOC et getBean

王林
Libérer: 2023-05-30 09:25:12
avant
1009 Les gens l'ont consulté

spring basic idea IOC

Le deuxième est la réflexion Java. Le mécanisme de réflexion est un noyau d'implémentation important de Spring Aujourd'hui, lorsque j'examinais le cache de troisième niveau de Spring pour résoudre le problème de. références circulaires, j'ai trouvé un bean. Le cycle de vie d'un objet Java est très similaire au processus de génération d'objets Java et j'ai découvert que le processus d'une instance de bean à partir de zéro est très intéressant. un code extrêmement élégant pour réaliser l'utilisation de Reflection et diverses structures de données cartographiques réalisent la production de pipeline de beans, ce qui est très élégant, j'ai donc essayé d'utiliser la réflexion pour écrire un gadget qui génère à l'envers des objets d'instance.

Ensuite, vous devez connaître au préalable le processus de génération d'un objet :

Je résume le processus de création d'objet comme suit :

Vérifiez si le pool constant existe La référence symbolique de l'objet est utilisée pour déterminer s'il a subi le processus de chargement de classe. Sinon, le processus de chargement de classe est effectué.

Allouer de la mémoire pour les nouveaux objets (deux méthodes : collision de pointeurs et liste libre) et attribuez W à 0 pour les autres espaces mémoire à l'exception de l'en-tête de l'objet.

Définissez l'en-tête de l'objet.

Initialisation de l'objet, c'est le processus d'exécution de votre méthode constructeur et d'attribution des valeurs que vous souhaitez définir aux champs dont vous avez besoin.

Ajoutez les détails : dans le processus d'allocation de mémoire pour de nouveaux objets, tout d'abord, la taille de mémoire requise par un objet une fois le chargement de la classe terminé est en fait complètement déterminée. en java Divisez un morceau de mémoire tout aussi grand dans le tas, mais comment le diviser ? Si la disposition de la mémoire du tas Java est allouée dans un ordre strict, c'est-à-dire qu'un côté est utilisé et l'autre côté est libre, alors la mémoire sera allouée par collision de pointeur. Ce qu'on appelle le pointeur est collecté au niveau de la ligne de démarcation. entre la zone libre et la zone utilisée. Lorsque de la mémoire est requise, le pointeur recule jusqu'à ce que la longueur couverte par le déplacement soit égale à la taille de mémoire requise par l'objet Java et s'arrête et alloue. Mais que se passe-t-il si la disposition de la mémoire du tas Java est fragmentée et discontinue ? Nous ne pouvons conserver qu'une liste qui enregistre les informations sur la taille et l'emplacement de toutes les zones libres du tas Java. Lors de l'allocation, il nous suffit de trouver l'allocation de zone la plus appropriée pour les nouveaux objets.

La capacité du garbage collector et sa capacité à effectuer la compression et le tri de l'espace déterminent si le tas Java est régulier. Lorsque les collecteurs que nous utilisons sont Serial et Parnew, ils sont alloués par collision de pointeurs. Lorsque nous utilisons le garbage collector CMS, nous devons utiliser l'allocation de table de zone libre gênante.

Ici, nous nous concentrons sur le remplissage des attributs et des méthodes : l'âme d'un objet, ce sont ses attributs et ses méthodes :

Les attributs de base utilisés par l'ensemble de l'outil : # 🎜🎜#

    private static volatile Constructor<?> constructor;
    private static volatile Object newInstance;
    private static volatile Map<String, Method> methodMap;
Copier après la connexion

Jetons d'abord un coup d'œil aux fonctions de ces méthodes :

  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;
        }
    }
Copier après la connexion

Obtenez le constructeur du type Notez qu'il s'agit d'une construction sans argument si vous n'en avez pas. constructeur sans argument, c'est très utile. Une erreur peut être signalée, car nous ne savons pas combien d'attributs il possède, n'est-ce pas (rappelez-vous toujours que nous faisons de l'ingénierie inverse !!! Nous ne savons pas ce qu'il y a dans ce type ? !!! Tout est information apportée par réflexion)

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()));
        }
    }
Copier après la connexion
# 🎜🎜#Récupérez les attributs et remplissez les valeurs des attributs. Les attributs sont également inclus ici.

 public static Method[] getMethodArray(Object dataType) {
        return dataType.getClass().getDeclaredMethods();
    }
Copier après la connexion

Obtenez toutes les méthodes pour former un tableau de méthodes.

  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);
        }
    }
Copier après la connexion

Enregistrez la méthode dans la collection de méthodes pour le stockage.

 public static Object useMethod(String methodName, @Nullable Object... parameters) throws Exception {
        return methodMap.get(methodName).invoke(newInstance, parameters);
    }
Copier après la connexion

La méthode d'utilisation est par son nom.

    @SneakyThrows
    public static Object getBean(Object dataType, Map<String, Object> parameterMap) {
        fillValueToNewInstance(dataType, parameterMap);
        fillMethodMap(dataType);
        return newInstance;
    }
Copier après la connexion

méthode getBean.

  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"));
    }
Copier après la connexion

Méthode de test. Les informations de type sont les suivantes :

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;;
    }
}
Copier après la connexion

Les résultats du test sont les suivants :

Comment SpringBoot utilise la réflexion pour simuler IOC et getBeanIci, nous n'utilisons pas Personne personne = new Person(); L'objet est instancié par réflexion.

Je vais lister les méthodes de réflexion utilisées :

getDeclaredFields Récupère l'objet d'attribut de domaine

getName Récupère le nom de l'attribut

#🎜 🎜#getType Obtenez le fichier de bytecode du type d'attribut

setAccessible(true) Définissez le cracking par force brute et obtenez l'utilisation des attributs privés

getDeclaredMethods Obtenez tous les tableaux de méthodes# 🎜🎜#

getClass Récupère le fichier de bytecode

getConstructor Récupère le constructeur sans argument

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:yisu.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!