Mode proxy (quinze)

Croyez en vous, s'il vous plaît croyez en vous

Le chapitre précédent a brièvement présenté le mode poids mouche (14), si vous ne l'avez pas lu, veuillez regarder le chapitre précédent

1. Mode proxy

Reportez-vous à l'introduction du modèle de proxy dans le didacticiel des débutants : https://www.runoob.com/design-pattern/proxy-pattern.html

Dans Proxy Pattern, une classe représente la fonctionnalité d'une autre classe. Ce type de modèle de conception est un modèle structurel.

Dans le modèle Proxy, nous créons des objets avec des objets existants afin de fournir une interface fonctionnelle avec le monde extérieur.

1.1 Introduction

Intention : Fournir un proxy pour d'autres objets afin de contrôler l'accès à cet objet.

Résoudre principalement : les problèmes causés par l'accès direct aux objets, par exemple : l'objet auquel il faut accéder se trouve sur une machine distante. Dans un système orienté objet, pour certaines raisons (telles que la création d'objets coûte cher, ou certaines opérations nécessitent un contrôle de sécurité ou nécessitent un accès hors processus), l'accès direct apportera beaucoup de problèmes aux utilisateurs ou aux structures du système. Nous pouvons ajouter une couche d'accès à cet objet lors de l'accès à cet objet.

Quand l'utiliser : Vous voulez un certain contrôle sur l'accès à une classe.

Comment résoudre : Augmentez la couche intermédiaire.

Code clé : combinaison de l'implémentation et de la classe déléguée.

Exemples d'application : 1. Raccourcis sous Windows. 2. Zhu Bajie est allé trouver Gao Cuilan, mais Sun Wukong l'a changé. Cela peut être compris de cette manière : l'apparence abstraite de Gao Cuilan, Gao Cuilan elle-même et Sun Wukong ont réalisé cette interface. Classe proxy. 3. Pour acheter un billet de train, vous n'êtes pas obligé de l'acheter à la gare, vous pouvez également vous rendre au bureau de vente. 4. Un chèque ou un certificat de dépôt bancaire est le proxy pour les fonds dans le compte. Les chèques sont utilisés dans les transactions sur le marché à la place des espèces et permettent de contrôler les fonds dans le compte de l'émetteur. 5. printemps aop.

Avantages : 1. Responsabilités claires. 2. Haute évolutivité. 3. Intelligente.

Inconvénients : 1. En raison de l'ajout d'objets proxy entre le client et le sujet réel, certains types de modes proxy peuvent ralentir la vitesse de traitement des requêtes. 2. La mise en œuvre du mode proxy nécessite un travail supplémentaire et la mise en œuvre de certains modes proxy est très compliquée.

Scénarios d'utilisation : divisés par responsabilités, il existe généralement les scénarios d'utilisation suivants : 1. Agent distant. 2. Agent virtuel. 3. Agent de copie sur écriture. 4. Agent de protection ou d'accès. 5. Agent de cache. 6. Agent de pare-feu. 7. Agent de synchronisation. 8. Agent de référence intelligent.

Remarque : 1. La différence avec le mode adaptateur : le mode adaptateur modifie principalement l'interface de l'objet considéré, tandis que le mode proxy ne peut pas modifier l'interface de la classe proxy. 2. La différence avec le mode décorateur : le mode décorateur est d'améliorer la fonction, et le mode proxy est de contrôler.

insérez la description de l'image ici

2. Mode proxy

Il existe un proxy statique, un proxy dynamique (proxy JDK) et un proxy Cglib (peut créer des objets dynamiquement en mémoire)

2. Un proxy statique

2.1.1 Interface de cours du professeur

public interface ITeacher {
    
    

    public void talk();
}

2.1.2 Interface réalisation d'un cours magistral

@Slf4j
public class RealTeacher implements ITeacher{
    
    

    @Override
    public void talk() {
    
    
        log.info("老师正在讲课");
    }
}

2.1.3 Ne pas utiliser de proxy

 @Test
    public void noProxyTest() {
    
    
        ITeacher iTeacher = new RealTeacher();
        iTeacher.talk();
    }

INFO [main] (RealTeacher.java:16) - Le professeur donne un cours magistral

2.1.4 Utilisation du proxy

@Slf4j
public class TeacherProxy implements ITeacher{
    
    
    private ITeacher iTeacher ;

    public TeacherProxy (ITeacher iTeacher) {
    
    
        this.iTeacher = iTeacher;
    }

    @Override
    public void talk() {
    
    
        log.info("老师提前备课--> 用户 prepare 操作");
        iTeacher.talk();
        log.info("老师课后总结--> 用户 after 操作");
    }

}

2.1.5 Méthode de test par procuration

@Test
    public void oneTest() {
    
    
        RealTeacher realTeacher = new RealTeacher();
        TeacherProxy teacherProxy = new TeacherProxy(realTeacher);
        teacherProxy.talk();
    }

image-20230615145810997

2.2 Proxy dynamique

2.2.1 Interface

public interface ITeacher2 {
    
    

    public void talk();

    public void hello (String name);
}

2.2.2 Implémentation de l'interface

@Slf4j
public class RealTeacher2 implements ITeacher2{
    
    

    @Override
    public void talk() {
    
    
        log.info("老师正在讲课");
    }

    @Override
    public void hello(String name) {
    
    
        log.info("你好啊 {}", name);
    }
}

2.2.3 Implémentation du proxy JDK

@Slf4j
public class TeacherProxy2 {
    
    

    private Object target ;

    public TeacherProxy2 (Object target) {
    
    
        this.target = target;
    }

    /**
     获取动态代理
     */
    public Object getProxyInstance() {
    
    
        return Proxy.newProxyInstance(
                target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new InvocationHandler() {
    
    
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    
                        log.info("JDK代理开始");

                        Object returnVal = method.invoke(target, args);

                        log.info("JDK代理结束");
                        return returnVal;
                    }
                }
        );
    }

}

2.2.4 Test proxy

   @Test
    public void twoTest() {
    
    
        ITeacher2 teacher2 = new RealTeacher2();
        // 处理转换代理信息
        ITeacher2 target = (ITeacher2)(new TeacherProxy2(teacher2).getProxyInstance());
        // 进行处理
        target.hello("张三");
    }

image-20230615150102593

2.3 Proxy Cglib

Deux. Trois. Une classe commune

@Slf4j
public class RealTeacher3 {
    
    

    public void talk() {
    
    
        log.info("老师正在讲课");
    }

    public void hello(String name) {
    
    
        log.info("你好啊 {}", name);
    }
}

2.3.2 Proxy TeacherProxy3 pour cette classe

@Slf4j
public class TeacherProxy3 implements MethodInterceptor {
    
    
    private Object target;
    public TeacherProxy3(Object target) {
    
    
        this.target = target;
    }
    
    public Object getProxyInstance () {
    
    
        // 创建工具类 Enhancer
        Enhancer enhancer = new Enhancer();
        // 设置父类
        enhancer.setSuperclass(target.getClass());
        // 设置回调函数, 主要是这个。
        enhancer.setCallback(this);
        // 创建子类对象,即代理对象
        return enhancer.create();
    }
    
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
    
    
        log.info("CGLIB 代理开始");

        Object returnVal = methodProxy.invoke(target, objects);

        log.info("CGLIB 代理结束");
        return returnVal;
    }

}

2.3.3 Test proxy

@Test
    public void threeTest() {
    
    
        RealTeacher3 realTeacher3 = new RealTeacher3();
        // 处理转换代理信息
        RealTeacher3 target = (RealTeacher3)new TeacherProxy3(realTeacher3).getProxyInstance();
        // 进行处理
        target.hello("张三");
    }

image-20230615150340055

3. Agent JDK de Hutool

Vous pouvez utiliser ProxyUtil ProxyFactory de hutool pour le proxy

@Test
    public void fourTest() {
    
    
        ITeacher2 teacher2 = new RealTeacher2();

        ITeacher2 proxy = ProxyUtil.proxy(teacher2, new SimpleAspect());

        proxy.hello("hutool 工具类的代理");

        ITeacher2 proxy2 = ProxyFactory.createProxy(teacher2, new Aspect() {
    
    
            @Override
            public boolean before(Object target, Method method, Object[] args) {
    
    
                log.info(">>>> 代理之前执行的操作");
                return true;
            }

            @Override
            public boolean after(Object target, Method method, Object[] args, Object returnVal) {
    
    
                log.info(">>>> 代理之后执行的操作");
                return true;
            }

            @Override
            public boolean afterException(Object target, Method method, Object[] args, Throwable e) {
    
    
                log.info(">>>> 异常时执行的操作");
                return true;
            }
        });
        proxy2.hello("hutool 工厂的代理");
    }

image-20230615150904736

L'objet proxy dynamique créé par CGLIB a des performances supérieures à l'objet proxy dynamique créé par JDK, mais il faut beaucoup plus de temps à CGLIB pour créer l'objet proxy qu'à JDK.

Par conséquent, pour les objets singleton, puisqu'il n'est pas nécessaire de créer fréquemment des objets, il convient d'utiliser CGLIB, sinon il est plus approprié d'utiliser la méthode JDK.

Dans le même temps, comme CGLib utilise la méthode de création dynamique de sous-classes, il ne peut pas utiliser la méthode modifiée finale.


Le code de ce chapitre est placé sur github :


https://github.com/yuejianli/DesignPattern/tree/develop/Proxy


Merci d'avoir regardé, si vous l'aimez, suivez-moi, merci encore !!!

Je suppose que tu aimes

Origine blog.csdn.net/yjltx1234csdn/article/details/131228558
conseillé
Classement