Mécanisme de recherche-réflexion de stage JAVA et agent dynamique

Présentation

Avant l'émergence de la réflexion, lorsque nous avons une classe java, nous ne pouvons pas utiliser la structure privée dans la classe en dehors de la classe, par exemple, nous ne pouvons pas appeler le constructeur privé, la méthode privée, etc. Mais après réflexion, on peut appeler n'importe quelle structure de cette classe, y compris privée.

import org.junit.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ReflectionTest {

    @Test
    public void test1(){
        Person p = new Person("tom",23);
        p.show();
    }


    @Test
    public void test2() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //1.获取类对象
        Class<Person> personClass = Person.class;
        //2.获取类对象的构造器
        Constructor constructor = personClass.getConstructor(String.class, int.class);
        Object tom = constructor.newInstance("Jerry", 23);
        //3.获取类方法
        Method show = personClass.getDeclaredMethod("show");
        show.invoke(tom);

        //反射的特殊功能,可以调用私有的类结构
        Constructor<Person> cons1 = personClass.getDeclaredConstructor(String.class);
        cons1.setAccessible(true);
        Person wanglei = cons1.newInstance("wanglei");
        wanglei.show();


    }

}

Mode réflexion et singleton

Le modèle singleton privatise le constructeur, et j'espère qu'une seule instance de cette classe doit être créée. A ce moment-là, la réflexion est de résoudre le problème de son utilisation. Le mode singleton est de suggérer votre écriture. Ils ne sont pas en conflit.

Compréhension de java.lang.Class

La classe comme source de réflexion

(1) Processus de chargement de classe: Une fois le programme compilé par javac.exe, un ou plusieurs fichiers de bytecode seront générés. La classe se termine, chaque classe java correspond à un fichier de bytecode, via l'interprétation java.exe pour exécuter un certain Le fichier de bytecode de la méthode mian. Cela équivaut à charger ce fichier de bytecode dans la mémoire. Ce processus est appelé chargement de classe. La classe enregistrée en mémoire est appelée la classe d'exécution, et cette classe d'exécution est utilisée comme une instance de Class. En d'autres termes, une instance de Class correspond à une classe d'exécution.

Quatre façons d'obtenir des objets de classe

//方式一:调用运行时类的属性:.class
        Class clazz1 = Person.class;
        System.out.println(clazz1);
        //方式二:通过运行时类的对象,调用getClass()
        Person p1 = new Person();
        Class clazz2 = p1.getClass();
        System.out.println(clazz2);

        //方式三:调用Class的静态方法:forName(String classPath)
        Class clazz3 = Class.forName("com.atguigu.java.Person");
//      clazz3 = Class.forName("java.lang.String");
        System.out.println(clazz3);

        System.out.println(clazz1 == clazz2);
        System.out.println(clazz1 == clazz3);

        //方式四:使用类的加载器:ClassLoader  (了解)
        ClassLoader classLoader = ReflectionTest.class.getClassLoader();
        Class clazz4 = classLoader.loadClass("com.atguigu.java.Person");
        System.out.println(clazz4);

        System.out.println(clazz1 == clazz4);

Trois étapes:

Charger: ajoutez le fichier de classe de la classe à la mémoire et créez un objet Classe. Ce processus est terminé par le chargeur de classe

Lien: assurez-vous que les informations contenues dans le flux d'octets du fichier de classe répondent aux exigences de la machine virtuelle actuelle et ne compromettent pas la sécurité de la machine virtuelle elle-même.

Initialisation: lors de la compilation et de la génération d'un fichier de classe, le compilateur génère deux méthodes à ajouter au fichier de classe, l'une est la méthode d'initialisation de classe clinit et l'autre est la méthode d'initialisation d'instance init. clinit se réfère au constructeur de classe, le rôle principal est d'effectuer dans la phase d'initialisation du processus de chargement de classe, le contenu d'exécution comprend l'initialisation de variable statique et l'exécution de bloc statique.

 

 

Présentation

Le modèle de proxy est l'un des 23 modèles de conception, ce qui est une connaissance plus importante.Le plus important AOP (Aspect Oriented Programing) dans le cadre de Spring est également basé sur un proxy dynamique.

Compréhension de l'agent

En ce qui concerne la compréhension des agents, permettez-moi de donner un exemple: il y a 20 ans, la façon dont nous voulions acheter un ordinateur Lenovo était: nous sommes allés à l'usine de Lenovo, et l'usine nous a vendu des ordinateurs et fourni des services après-vente.

Au cours de ces décennies, certains concessionnaires sont apparus. Ils ont acheté des produits à l’usine Lenovo et nous les ont revendus. Lorsque l’ordinateur est tombé en panne, nous sommes également allés au magasin du concessionnaire pour le trouver, puis il est allé à l’usine. La connexion avec l'usine a en fait été rompue.

En 2020, si nous voulons acheter un ordinateur portable, nous irons directement chez de grands distributeurs tels que Tmall, Suning et JD.com pour acheter un ordinateur. En cas de problème, nous retournerons le produit sans motif pendant 7 jours.

Ici, nous sommes le client client, ces concessionnaires sont également appelés agents et les usines Lenovo sont appelées agents. Un tel processus est un agent.

Proxy dynamique

Les caractéristiques du proxy dynamique: le code d'octet est créé et chargé à tout moment, et chargé à tout moment

Le rôle des agents dynamiques: améliorer la méthode sans modifier le code source

Classification des agents dynamiques: 2 types, l'un est un agent dynamique basé sur l'interface et l'autre est un agent dynamique basé sur une sous-classe

Proxy dynamique basé sur une interface

L'implémentation de classe proxy fournie par JDK nécessite que la classe proxy implémente au moins une interface. Le processus de mise en œuvre est le suivant

(1) Créez d'abord la classe Lenovo et implémentez une interface

package com.alibaba200408.动态代理;

public class Lenovo implements ILenovo {
    @Override
    public void sale(Double money) {
        System.out.println("拿到"+money+"元,电脑发货");
    }

    @Override
    public void afterService(Double money) {
        System.out.println("拿到"+money+"元,售后服务开始");

    }
}

Le code est très simple, seules deux méthodes sont impliquées, l'une consiste à vendre l'ordinateur et l'autre à réparer l'ordinateur.

Le code de l'interface est le suivant

package com.alibaba200408.动态代理;

public interface ILenovo {

    void sale(Double money);

    void afterService(Double money);
}

(2) Instancier un objet proxy dynamique et des méthodes d'appel via l'objet proxy

package com.alibaba200408.动态代理;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class Client {
    public static void main(String[] args) {

        //联想厂家
        ILenovo lenovo = new Lenovo();


        //创建代理对象
        ILenovo proxyInstance = (ILenovo) Proxy.newProxyInstance(lenovo.getClass().getClassLoader(),
                lenovo.getClass().getInterfaces(),
                new InvocationHandler() {
                    /**
                     * invoke方法的作用是调用任何被代理对象的方法都会被这个invoke方法拦截
                     *  proxy:表示当前代理对象的引用
                     *  method:表示当前正在执行的方法
                     *  args:表示当前执行的方法的参数
                     *
                     *  返回值就是当前方法的返回值
                     */

                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        //提供增强的代码
                        Double money = (Double) args[0];
                        if ("sale".equals(method.getName())){
                            method.invoke(lenovo, money * 0.8);
                        }else {
                            method.invoke(lenovo,args);
                        }

                        return null;
                    }
                });

        proxyInstance.afterService(10000.0);

    }
}

Agent dynamique basé sur une sous-classe

Cette implémentation nécessite que la classe proxy ne puisse pas être finale, car la classe modifiée finale ne peut pas avoir de sous-classes, et deuxièmement, cette méthode nécessite un cglib tiers. Je ne les répéterai pas ici.

A publié 111 articles originaux · Comme 60 · 70 000 + vues

Je suppose que tu aimes

Origine blog.csdn.net/Haidaiya/article/details/105512739
conseillé
Classement