Three proxy modes in Java, waiting for proxy, dynamic proxy, Cglib proxy

Three proxy modes in Java, waiting for proxy, dynamic proxy, Cglib proxy

Agency model

Proxy is a design pattern that provides a way to access the target object indirectly; that is, access the target object through the proxy object. The advantage of this is that it can add additional functional supplements to the functions implemented by the target object. That is to extend the function of the target object.

This conforms to the opening and closing principle of the design pattern, which is to expand the function without changing the existing code.

Give an example to illustrate the role of agency: the relationship between the celebrity and the agent is the relationship between the agent and the agent. When the celebrity is acting in an event, the celebrity is a target. He only needs to be responsible for the program in the event, and other trivial matters will be handed in. To his agent (broker)

To solve. This is an example of agency thinking in reality.

Static proxy

When using a static proxy, the proxy object and the proxy object need to implement the same interface or inherit the same parent class, so an interface or abstract class must be defined.

Code case:

Copy 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();
  }
}

Static proxy summary:

  • Advantages: It can expand the target function without modifying the function of the target object.
  • Disadvantages: Because the proxy object needs to implement the same interface as the target object, there will be many proxy classes and too many classes. At the same time, once the interface adds methods, the target object and the proxy object must be maintained.

The dynamic proxy method can solve the above problems

Dynamic proxy

The main feature of dynamic proxy is that JVM can generate proxy objects for proxied objects when the program is running.

The often-speaking dynamic proxy is also called JDK proxy, which is also a kind of interface proxy. The proxy class that generates proxy objects in the JDK is Proxy, and the package is 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();
    }
}

to sum up:

The proxy object does not need to implement the interface, but the target object must implement the interface, otherwise the dynamic proxy cannot be used, so this is also a defect of this approach.

Cglib proxy

The above static proxy and dynamic proxy mode have the same point that they both require the target object to be an object that implements an interface, but not any object will implement an interface, and there are also objects that do not implement any interface.

At this time, you can use the inherited target class to implement the proxy in the way of the target object subclass. This method is called: Cglib proxy, also called subclass proxy, which builds a subclass object in memory to achieve the target object function Extension.

One limitation of using JDK dynamic proxy is that the object being proxied must implement one or more interfaces.If you want to proxy a class that does not implement the interface, you need to use Cglib to implement it.

Since Cglib is provided by a third party, you need to import the relevant jar package when using it. There are two packages as shown in the figure:

Code case:

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;
                }
            }
        }
    }
}

to sum up:

In Spring's AOP programming:

  • If the target object added to the container has an implementation interface, use the JDK proxy
  • If the target object does not implement the interface, use the Cglib proxy.

Tags: static proxy, dynamic proxy, cglib dynamic proxy

Guess you like

Origin blog.csdn.net/weixin_43941676/article/details/108268890