java core foundation of the proxy mechanism Comments (static agents, dynamic agent: JDK, CGlib)

(A) What is a proxy?

Often encounter in life agents, such as we are to find an intermediary to buy a house, rather than trying to pick a building a building, where the intermediary is the agent. That proxy proxy object to access the target object through , but also can enhance additional functions in the target object basis. java agent is divided into static and dynamic proxy agent. Static agent that is before the code is run, the proxy class has existed. Refers to dynamic proxy agent class is not written in the code, but generated during operation.

(B) the static agent

Static agent before the code is run, the proxy class has existed. Static agent through a simulated example;:

To rent, for example, rent in two ways, one is to rent directly to the landlord, the other is looking to rent software such as freely (not advertising), which is accessed through a proxy target object.

First create a new interface rent, rent with only one method:

public interface Renting {
    String rent(String name);
}

Then create a Person class that implements the interface, this class means that rent directly to the landlord, which is the target audience:

public class Person implements Renting{
    @Override
    public String rent(String name) {
        return "租了"+name;
    }
}

Then create a proxy class Ziru, you can go directly accessed by the target through a proxy class, we've also talked about the proxy class can only achieve access to the target object, it can also enhance the additional functionality in the target object basis. So add a service charge additional functionality class.

public class Ziru implements Renting{
    Person person;
    public Ziru(){
        person=new Person();
    }
    @Override
    public String rent(String name) {
        System.out.println("收取手续费");
        return person.rent(name);
    }
}

There are two ways: using a proxy and do not use a proxy to access the target object:

public class run {
    public static void main(String[] args) {
          //不使用代理
//        Person person=new Person();
//        person.rent("碧桂园");
          //使用代理
          Ziru ziru=new Ziru();
          System.out.println(ziru.rent("碧桂园"));
    }
}

Get the results.

(C) dynamic proxies

Refers to dynamic proxy agent class is not written in the code, but generated during operation. java dynamic proxy provides two ways, which are based on dynamic agent Jdk and based Cglib dynamic proxy.

(3.1) based on the Proxy Jdk

First introduced on Jdk of Proxy, continue to use the case of renting:

Renting and wherein the same code and Person above static agents , JdkProxy a new class that is a core part of the dynamic proxy, InvocationHandler implement the interface. InvocationHandler is an interface, InvocationHandler each proxy instance has an associated implementation class, if the method is called the agent, the agent will notify InvocationHandler and forwarded to the internal implementation class invoke, by its realization process content. Another core of this code is the Proxy.newProxyInstance, this method requires three parameters, object proxy class is generated during operation , the function of each parameter has been written in a comment. This code means that Proxy proxy object dynamically generated calls InvocationHandler implementation class invoke.

public class JdkProxy implements InvocationHandler {
    Renting obj;

    public Renting getProxy(Renting obj){
        this.obj=obj;
        //运行期间创建对象
        Object proxy = Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
        //obj.getClass().getClassLoader()类加载器
        //obj.getClass().getInterfaces() 目标类实现的接口
        //InvocationHandler对象
        return (Renting) proxy;
    }

    //proxy 代理对象
    //method 要实现的方法
    //args 方法的参数
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //拿到目标方法执行结果
        Object invoke = method.invoke(obj, args);
        return invoke;
    }
}

Next is the implementation class:

public class run {
    public static void main(String[] args) {
        Person person=new Person();
        JdkProxy jdkProxy=new JdkProxy();
        Renting proxy = jdkProxy.getProxy(person);
        String res = proxy.rent("碧桂园");
        System.out.println(res);
    }
}

When you call proxy.rent () method, it is performed automatically invoke methods to achieve dynamic proxy.

You can add some of your own code to invoke methods, for example, I wrote in invoke a method

It will be printed on the console is running, and this is the core Spring AOP

JDK InvocationHandler dynamic proxy class implements the interface, invoke overridden methods.

JDK dynamic proxies based reflection (Method.invoke (object parameter)) the Proxy.newProxyInstance ()

(3.2) based on dynamic agent of Cglib

CGlib can be achieved by dynamic proxy, introducing two asm-3.3.1 jar package before writing the code, cglib-2.2.2

CGlib achieve dynamic proxy, in which the same Renting and Person code and static agent , there will no longer show. CGlib can also directly proxy class, for comparison, here still use the interface . New CglibProxy, realized MethodInterceptor interface, which need to implement the intercept method. intercept method still call method.invoke () method. And Jdk difference is the way to create a proxy object, CGlib Enhance used to create a proxy object.

public class CglibProxy implements MethodInterceptor {
    Renting obj;
    //通过Enhance动态创建对象
    public Renting getProxy(Renting obj){
        this.obj=obj;
        Enhancer enhancer=new Enhancer();
        //设置父类
        enhancer.setSuperclass(obj.getClass());
        //设置回调方法
        enhancer.setCallback(this);
        return (Renting) enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        Object invoke = method.invoke(obj, objects);
        return invoke;
    }
}

Next is the implementation class:

public class run {
    public static void main(String[] args) {
        Person person=new Person();
        CglibProxy cglibProxy=new CglibProxy();
        Renting proxy = cglibProxy.getProxy(person);
        String res = proxy.rent("碧桂园");
        System.out.println(res);
    }
}

got the answer:

(D) summary

1.JDK dynamic proxy can only proxy for the interface, not the class of ordinary proxy (as the parent of all the generated proxy class for Proxy, Java class inheritance mechanism does not allow multiple inheritance); CGLIB able to delegate to the general category;

2.JDK dynamic proxy uses reflection API Java native operating, based on the more efficient generation; CGLIB-frame using ASM bytecode directly operate during the execution of the more efficient class

Published 64 original articles · won praise 785 · views 80000 +

Guess you like

Origin blog.csdn.net/qq_41973594/article/details/104118797