Trois modes de proxy en Java, en attente de proxy, proxy dynamique, proxy Cglib

Trois modes de proxy en Java, en attente de proxy, proxy dynamique, proxy Cglib

Modèle d'agence

Le proxy est un modèle de conception qui permet d'accéder indirectement à l'objet cible, c'est-à-dire d'accéder à l'objet cible via l'objet proxy. L'avantage est qu'il peut ajouter des compléments fonctionnels supplémentaires aux fonctions implémentées par l'objet cible. est d'étendre la fonction de l'objet cible.

Cela est conforme au principe d'ouverture et de fermeture du modèle de conception, qui consiste à étendre la fonction sans modifier le code existant.

Donnez un exemple pour illustrer le rôle de l'agence: la relation entre la célébrité et l'agent est la relation entre l'agent et l'agent. Lorsque la célébrité joue dans un événement, la célébrité est une cible. Il lui suffit d'être responsable du programme de l'événement, et d'autres questions insignifiantes seront remises. À son agent (courtier)

À résoudre. Ceci est un exemple de la pensée de l'agence dans la réalité.

Proxy statique

Lors de l'utilisation d'un proxy statique, l'objet proxy et l'objet proxy doivent implémenter la même interface ou hériter de la même classe parent, donc une interface ou une classe abstraite doit être définie.

Cas du code:

Copier le code

// 接口
interface IStar {
    
    
  void sing();
}

// 真实对象
class LDHStar implements IStar {
    
    
  @Override
  public void sing() {
    
    
      System.out.println("刘德华唱歌");
  }
}

// 代理类需要有真实对象的控制权 (引用)
class ProxyManger implements IStar {
    
    
  
  // 真实对象的引用
  private IStar star;
  
  public ProxyManger() {
    
    
      super();
  }

  public ProxyManger(IStar star) {
    
    
      super();
      this.star = star;
  }
  
  @Override
  public void sing() {
    
    
   System.out.println("唱歌前准备");
   star.sing();
   System.out.println("善后工作");        }
}
class Test{
    
    
	public static void main(String[] args) {
    
    
      // 创建明星对象
      IStar ldh = new LDHStar();
      ProxyManger proxy = new ProxyManger(ldh);
      proxy.sing();
  }
}

Résumé du proxy statique:

  • Avantages: Il peut étendre la fonction cible sans modifier la fonction de l'objet cible.
  • Inconvénients: étant donné que l'objet proxy doit implémenter la même interface que l'objet cible, il y aura de nombreuses classes proxy et trop de classes. En même temps, une fois que l'interface ajoute des méthodes, l'objet cible et l'objet proxy doivent être conservés.

La méthode de proxy dynamique peut résoudre les problèmes ci-dessus

Proxy dynamique

La principale caractéristique du proxy dynamique est que JVM peut générer des objets proxy pour les objets proxy lorsque le programme est en cours d'exécution.

Le proxy dynamique souvent parlé est également appelé proxy JDK, qui est également une sorte de proxy d'interface. La classe de proxy qui génère des objets proxy dans le JDK est Proxy et le package est java.lang.reflect

//目标类接口
interface IDog{
    
    
    void run();
}
//目标类
class GunDog implements IDog{
    
    

    @Override
    public void run() {
    
    
        System.out.println("猎狗在跑");
    }
}
class DogUtils{
    
    
    public static void method1() {
    
    
        System.out.println("增强方式一");
    }
    
    public static void method2() {
    
    
        System.out.println("增强方式二");
    }
}
class MyInvocationHandle implements InvocationHandler{
    
    
    private Object target;
    public void setTarget(Object target) {
    
    
        this.target = target;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    
            DogUtils.method1();
            method.invoke(target, args);
            DogUtils.method2();
            return null;
    }
}
    //生产代理对象的工厂
 class MyProxyFactory{
    
    
    public static Object getProxy(Object target) {
    
    
        MyInvocationHandle handle = new MyInvocationHandle();
        handle.setTarget(target);
        Object proxy = Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), handle);
        return proxy;
    }
 }
public class ProxyDemo {
    
    
    public static void main(String[] args) {
    
    
      IDog dog = new GunDog();
      IDog proxy =(IDog) MyProxyFactory.getProxy(dog);
      proxy.run();
    }
}

Pour résumer:

L'objet proxy n'a pas besoin d'implémenter l'interface, mais l'objet cible doit implémenter l'interface, sinon le proxy dynamique ne peut pas être utilisé, c'est donc également un défaut de cette approche.

Proxy Cglib

Le proxy statique et le mode proxy dynamique ci-dessus ont le même point qu'ils exigent tous deux que l'objet cible soit un objet qui implémente une interface, mais aucun objet n'implémentera une interface, et il existe également des objets qui n'implémentent aucune interface.

À ce stade, vous pouvez utiliser la classe cible héritée pour implémenter le proxy à la manière de la sous-classe d'objet cible. Cette méthode est appelée: proxy Cglib, également appelé proxy de sous-classe, qui crée un objet de sous-classe en mémoire pour réaliser la fonction d'objet cible Extension.

Une limitation de l'utilisation du proxy dynamique JDK est que l'objet en cours de proxy doit implémenter une ou plusieurs interfaces. Si vous voulez proxy une classe qui n'implémente pas l'interface, vous devez utiliser Cglib pour l'implémenter.

Étant donné que Cglib est fourni par un tiers, vous devez importer le package jar approprié lors de son utilisation. Il existe deux packages comme indiqué dans la figure:

Cas du code:

public class CglibProxy {
    
    

    public static void main(String[] args) {
    
    
        
        int[] arr = new int[100000];
        for (int i = 0; i < arr.length; i++) {
    
    
            arr[i] = (int) (Math.random() * 1000);
        }
        //实例化一个增强器,也就是cglib中的一个class generator
        Enhancer enhancer = new Enhancer();
        //设置目标类
        enhancer.setSuperclass(ArraySort2.class);
        //设置拦截对象,这里直接使用匿名内部类写法
        enhancer.setCallback(new MethodInterceptor() {
    
    
            @Override
            public Object intercept(Object object , Method method, Object[] args, MethodProxy proxy) throws Throwable {
    
    
                String sortName = method.getName();
                switch (sortName) {
    
    
                case "bubbleSort":
                    sortName = "冒泡排序";
                    break;
                case "selectSort":
                    sortName = "选择排序";
                    break;
                case "quickSort":
                    sortName = "快速排序";
                    break;
                default:
                    break;
                }
                long start = System.currentTimeMillis();
                //此处一定要使用proxy的invokeSuper方法来调用目标类的方法
                proxy.invokeSuper(object, args);
                long end = System.currentTimeMillis();
                System.out.println("本次" + sortName + "的执行时间为: " + (end -start) + "ms");
                return null;
            }
            
        });
        //生成代理类并返回一个实例
        ArraySort2 arraySort = (ArraySort2) enhancer.create();
        arraySort.bubbleSort(arr);
        arraySort.selectSort(arr);
        arraySort.quickSort(arr);
    }
    
}
class ArraySort2{
    
    
    public void quickSort(int[] arr) {
    
    
        Arrays.sort(arr);
    }
    public void selectSort(int[] arr) {
    
    
        for (int i = 0; i < arr.length; i++) {
    
    
            for (int j = i+1; j < arr.length; j++) {
    
    
                if (arr[i] > arr[j]) {
    
    
                    int temp = 0;
                    temp = arr[i];
                    arr[i] = arr[j];
                    arr[j] = temp;
                }
            }
        }
    }
    public void bubbleSort(int[] arr) {
    
    
        for (int i = 0; i < arr.length - 1; i++) {
    
    
            for (int j = 0; j < arr.length - 1 - i; j++) {
    
    
                if (arr[j] > arr[j + 1]) {
    
    
                    int temp = 0;
                    temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
    }
}

Pour résumer:

Dans la programmation AOP de Spring:

  • Si l'objet cible ajouté au conteneur a une interface d'implémentation, utilisez le proxy JDK
  • Si l'objet cible n'implémente pas l'interface, utilisez le proxy Cglib.

Tags: proxy statique, proxy dynamique, proxy dynamique cglib

Je suppose que tu aimes

Origine blog.csdn.net/weixin_43941676/article/details/108268890
conseillé
Classement