java Learning Notes (Intermediate) - JDK Dynamic Agent

Posted by newb on Thu, 15 Aug 2019 15:01:50 +0200

I. What is the Agency Model

I believe you all know the concept of agent. In business, agents are everywhere. Assuming you are going to buy something, you can not go to the real manufacturer to buy, nor can you directly demand from the manufacturer, the agent is a bridge between the buyer and the manufacturer. If you want to buy or customize what products, what specifications, styles and prices you need to communicate directly with the agent, the agent communicates with the real manufacturer, so that the buyer can consult the agent if he has any problems, and the real manufacturer can also concentrate on the product, do not need to take care of other matters, and the buyer can not intervene in the factory. Business.

In the above relationship, the manufacturer is the agent object, the agent is the agent object, and the buyer is the caller. There are many dynamic proxy technologies in java, including JDK, CGLIB, Javassist, etc. Here I will compare CGLIB with JDK dynamic proxy.

Significance

The meaning of dynamic proxy is to generate a space occupying (proxy object) to proxy the real object, so as to achieve the purpose of controlling the real object. To understand dynamic proxy, first of all, we need to have the knowledge of reflection.

3. Steps to Realize Dynamic Agent

The implementation of agent is divided into two main steps:

1. Establishment of proxy relationship between proxy object and real object

2. The Logical Method of Implementing Proxy Objects

IV. JDK Dynamic Agent

JDK dynamic proxy, JDK's own functions, in the java.lang.reflect. * package. In order to realize JDk dynamic proxy, it is necessary to use interface to generate proxy objects.

1. First, define a simple interface HelloWorld.java

public interface HelloWorld {
    void sayHello();
}

2.HelloWorld implementation class HelloWorldImpl.java

public class HelloWorldImpl implements HelloWorld {
    @Override
    public void sayHello() {
        System.out.println("hello world");
    }
}

3. To establish proxy relationship, the interface Invocation Handler must be implemented. Invoke is the only method that needs to be implemented in the interface. The proxy logic implemented in the interface will be mapped to invoke when the proxy object scheduling method is used. In fact, it is realized by reflection. The bind() method is to establish the proxy relationship. Proxy's new Proxy Instance is used to create the proxy object. The first parameter class loader, the second parameter hanging interface, and the third parameter is the class that implements the proxy logic method invoke.

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class JdkProxy implements InvocationHandler {
    //Real object
    private Object target = null;

    /**
     * Establishing the relationship between real object and proxy object
     * @param target Into the real object
     * @return
     */
    public Object bind(Object target){
        this.target = target;
        return Proxy.newProxyInstance
            (target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),this);
    }

    /**
     *  Proxy logic
     * @param proxy Proxy object
     * @param method Current Scheduling Method
     * @param args Parameters of Scheduling Method
     * @return
     * @throws Throwable
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        System.out.println("Entry proxy logic method");
        System.out.println("Services before calling real objects");
        Object object = method.invoke(target,args);
        System.out.println("Services after calling real objects");
        return object;
    }
}

4. Testing

import org.junit.Test;

public class JdkProxyTest {

    @Test
    public void test_JdkProxy(){
        JdkProxy proxy = new JdkProxy();
        HelloWorld helloWorld = null;
        try {
            helloWorld = (HelloWorld) proxy
                .bind(Class.forName
            ("com.xcl.ssm.chapter2.jdkproxy.HelloWorldImpl")
                            .newInstance());
        } catch (Exception e) {
            e.printStackTrace();
        }
        helloWorld.sayHello();
    }
}

V. CGLIB Dynamic Agent

As mentioned above, the implementation of JDK dynamic proxy can only be realized by means of interface, while CGLIB does not need, only a non-abstract class is needed. Let's take the HelloWorldImpl class above as an example. There is no HelloWorld interface now. JDK dynamic proxy must implement invocationHandler interface, CGLIB must implement MethodInterceptor interface, there is only one method intercept(), which needs to implement proxy logic. Before you write your code, remember the package. This is a technology provided by a third party.

public class CglibProxy implements MethodInterceptor {

    /**
     *  Generating CGLIB proxy objects
     * @return
     */
    public Object getProxy(Class clz){
        //CGLIB Enhanced Class Objects
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(clz);
        //Setting the current object as the proxy logical object
        enhancer.setCallback(this);
        //Generate and return proxy objects
        return enhancer.create();
    }

    /**
     *  Agent Logic Method
     * @param proxy Proxy object
     * @param method Method
     * @param args parameter
     * @param methodProxy Method Agent
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        System.out.println("Before calling the real object");
        //Method of invoking real objects by reflection
        Object obj = methodProxy.invokeSuper(proxy,args);
        System.out.println("After calling the real object");
        return obj;
    }
}

VI. SUMMARY

To truly understand dynamic proxy, we need to be familiar with reflection mechanism. From the above code, we can see that the underlying implementation of dynamic proxy is still based on reflection. We know that reflection consumes performance, which brings some performance problems, but for the sake of simplicity in development, this sacrifice is worthwhile. The frameworks we have learned, such as spring, mybatis and so on, use a lot of dynamic proxy technology. Interested children's shoes can read the source code (which means I haven't seen a lot of source code), which uses a lot of design patterns, which is very helpful to improve their code level. Well, let's talk about it.~

Like my little friend remember to scan attention yo~

Topics: Java JDK Junit Spring