Home  >  Article  >  Java  >  what is java proxy

what is java proxy

angryTom
angryTomOriginal
2019-11-13 11:37:374661browse

what is java proxy

What is a java proxy?

What is a proxy? In fact, it is easy to understand, that is, it does not directly access the target. Instead, it is accessed through an intermediate layer, just like the following:

what is java proxy

Java's static proxy

For example, if Some of our fruits, such as bananas, apples, etc., written in Java code, probably look like this: (Recommended tutorial: java tutorial)

//Fruit.java/**
 * 水果的接口
 */public interface Fruit {    /**
     * 获取水果的名字
     */
    public String getName();
}//Apple.javapublic class Apple implements Fruit {    @Override
    public String getName() {        return "苹果";
    }
}//Banana.javapublic class Banana implements Fruit {    @Override
    public String getName() {        return "香蕉";
    }
}

To eat fruit, you have to peel it. You can't write a subclass for each fruit. The class handles the peeling. Therefore, we can make an agent and peel the apple before eating it. Just like the following, wrap the original fruit with one layer:

//PeelFruitProxy.java/**
 * 代理,让每个水果去皮
 */public class PeelFruitProxy implements Fruit {    private Fruit mFruit;    public PeelFruit(Fruit fruit) {        this.mFruit = fruit;
    }    @Override
    public String getName() {
        System.out.println("proxt:" + proxy.getClass().getName());        return "去皮的" + mFruit.getName();
    }
}

Added a test class, the test class is as follows:

//Main.javapublic class Main {    public static void main(String[] args) {
        Apple apple=new Apple();//原始的苹果
        Banana banana=new Banana();//原始的香蕉

        PeelFruitProxy peelApple=new PeelFruitProxy(apple);//代理,添加去皮功能
        PeelFruitProxy peelBanana=new PeelFruitProxy(banana);//代理,添加去皮功能
        System.out.println(peelApple.getName());
        System.out.println(peelBanana.getName());
    }
}

The above is the static proxy of Java. To put it simply, That is to wrap the original target object with a layer, add new things and then call the target itself. But if it is just such a static proxy, an interface requires a proxy, and is it very cumbersome to implement?

Java's dynamic proxy

In Java, there is a class that does this, called Proxy, which can directly use reflection and proxy interception. Let’s briefly introduce this class. In fact, the most commonly used static method is Proxt.newProxyInstance(), which is like this:

public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)

First we need to implement InvocationHandler, implement the invoke method, and call the target object. time, the invoke method will be called first, and the implementer needs to actively call the callee method in this method.

//FruitInvocationHandler.java/**
 * 调用方法拦截器
 */public class FruitInvocationHandler implements InvocationHandler {    private Fruit mFruit;    public FruitInvocationHandler(Fruit fruit) {        this.mFruit = fruit;
    }    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        String result = (String) method.invoke(mFruit, args);//需要在这个方法里面,主动调用被代理的对象。
        return "去皮的" + result;
    }
}

Run it:

//Main.Javapublic class Main {    public static void main(String[] args) {
        Apple apple = new Apple();
        Fruit proxyApple = (Fruit) Proxy.newProxyInstance(Fruit.class.getClassLoader(), new Class[]{Fruit.class}, new FruitInvocationHandler(apple));
        System.out.println(proxyApple.getClass().getName());
        System.out.println(proxyApple.getName());

        Banana banana = new Banana();
        Fruit proxyBanana = (Fruit) Proxy.newProxyInstance(Fruit.class.getClassLoader(), new Class[]{Fruit.class}, new FruitInvocationHandler(banana));
        System.out.println(proxyApple.getClass().getName());
        System.out.println(proxyBanana.getName());
    }
}

what is java proxy

This method is to generate a PeelFruitProxy as mentioned above (of course, the name we see is: com.sun .proxy.$Proxy0), it is dynamically generated to avoid having to write it every time. This is also the reason why it is called a dynamic proxy, because we can proxy any class at runtime. AOP in many programs is implemented in this way, but we found some characteristics. The second parameter of newProxyInstance() is a list of interfaces. Why is there this list?

Because our dynamically generated proxy class also needs to implement the interface, so that it can be easily transformed downward and use its methods. Otherwise, the generated class will have a class name like com.sun.proxy.$Proxy0. , and is in memory, the generated method cannot be called. ** Therefore, this dynamic proxy method has a fatal shortcoming, that is, the proxied class must implement the interface. **

CGLib proxy

cglib is a powerful, high performance and quality Code Generation Library, It is used to extend JAVA classes and implements interfaces at runtime.

Another well-known Java proxy implementation is CGLib (Code Generation Library), a code generation framework based on ASM, you can use it To dynamically generate classes and then implement interception of methods, you can avoid the problem of JDK's dynamic proxy, which requires the target class to implement the interface. In other words, CGLib can be used to generate the PeelFruitProxy mentioned above.

Let me briefly introduce how to use it. First of all, this CGLib is a third-party library. We need to depend on it:

compile 'cglib:cglib:3.2.8'

The latest version can be seen here (new version) [https://github.com/cglib/cglib/releases] Then let’s give it a try, let’s implement the above agent

//FruitMethodInterceptor.java/**
 * CGLib代理的方法拦截器
 */public class FruitMethodInterceptor implements MethodInterceptor{    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        String result = (String) proxy.invokeSuper(obj, args);//主要,这里调用的是父类,也就是说, 生成的类和原始类是继承关系
        return "去皮的"+result;
    }
}//Main.javapublic class Main {    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(Apple.class);
        enhancer.setCallback(new FruitMethodInterceptor());
        Apple apple = (Apple) enhancer.create();
        System.out.println(apple.getClass().getName());
        System.out.println(apple.getName());
    }
}

Run The effect is as follows:

what is java proxy

#We see that the same function is implemented, but Apple is no longer the original Apple class, it has become com.zjiecode.learn.java. proxy.Apple$$EnhancerByCGLIB$$44ade224, yes, we are actually using this class, not the original Apple. This class inherits from Apple, and finally implements the proxy for the Apple class. In this way, because inheritance is used, there is no need for the proxied class to implement the interface. Of course, he can also implement agents through interfaces.

Summary

The first type of proxy is not mentioned here. It is only suitable for a single interface proxy and is decided at compile time.

The second and third types of proxies are all dynamic proxies, but we see differences:

1) JDK’s dynamic proxy can only implement interface proxies and is a packaged proxy. Proxy object (instance of class), that is to say, during the proxy process, there are two objects, a proxy object and a target object. The target object is packaged in the proxy object.

2) CGLib's proxy inherits the target object, generates a new class, and then implements the proxy. In this way, there is a proxy object in the memory and no target object. Direct inheritance is used. Method

Generating proxy classes is at runtime, which is different from Javapoet which generates classes at compile time.

The above is the detailed content of what is java proxy. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn