Static agent, JDK dynamic agent, CGLIB dynamic agent

Posted by julzk on Sun, 26 Dec 2021 02:20:37 +0100

catalogue

I What is an agent

II Code implementation agent

I Static proxy

II JDK dynamic agent

III CGLIB dynamic proxy

I What is an agent

Imagine this scenario: we want to invite Jay to perform, but Jay only sings and doesn't want to do other trivial business. What else should we do at this time? At this time, of course, we need to find an agent to help Jay talk about salary, arrange itinerary and buy train tickets. This is equivalent to our agent model.

II Code implementation agent

First create the interface and implementation class of the target object

IJaySingService interface:

public interface IJaySingService {
    public String sing(String str);
}

JaySingService implementation class:

public class JaySingService implements IJaySingService {
    @Override
    public String sing(String str) {
        if ("Flower Sea".equals(str) ) {
            System.out.println("Don't you leave~Distance is inseparable~");
            return str;
        } else if ("Clearly".equals(str)) {
            System.out.println("Obviously, he is gentle~~~");
            return str;
        }
        return "Can't sing~~~~";
    }
}

I Static proxy

Directly declare the proxy object as an exit, implement the interface of the target object, implement its methods and enhance them

StaticProxy static proxy class:

public class StaticProxy implements IJaySingService{
    //The static proxy needs to inherit the target object and then override and enhance the method
    //Target object
    IJaySingService target;

    //Create constructor
    public StaticProxy(IJaySingService target) {
        this.target = target;
    }

    @Override
    public String sing(String str) {
        //What needs to be done before executing the target method
        System.out.println("You need to negotiate the performance fee with the agent before the performance");

        String result = target.sing(str);
        //What needs to be done after executing the target method
        System.out.println("After singing, the agent needs to arrange the return trip back");

        return result + "--Sounds good! Sounds good!";
    }
}

test:

public class Test01 {
    public static void main(String[] args) {
        //Create target object
        IJaySingService jaySingService = new JaySingService();
        //Call static proxy for enhancements
        StaticProxy proxy = new StaticProxy(jaySingService);
        String result = proxy.sing("Flower Sea");
        System.out.println(result);
    }
}

result:

You need to negotiate the performance fee with the agent before the performance
Don't you leave ~ distance is inseparable~
After singing, the agent needs to arrange the return trip back
Huahai -- good! Sounds good!

II JDK dynamic agent

The flexibility of static agent is not high, so we introduce the way of dynamic agent

If the target object implements an interface, we can use the JDK proxy pattern. JDK dynamic proxy is equivalent to the interface to implement the target object, and then rewrite and enhance its methods.

public class Test02 {
    public static void main(String[] args) {
        //Get target object
        IJaySingService target = new JaySingService();
        //Get dynamic proxy object
        IJaySingService proxy = (IJaySingService) Proxy.newProxyInstance(target.getClass().getClassLoader(),//Get class loader
                target.getClass().getInterfaces(), //Gets the interface of the target object
                new InvocationHandler() { //InvocationHandler class implementation
                    //The invoke method is executed when the proxy object executes the method
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        //What needs to be done before executing the target method
                        System.out.println("You need to negotiate the performance fee with the agent before the performance");
                        //Call the method of the target object
                        String result = (String) method.invoke(target,args);

                        //What needs to be done after executing the target method
                        System.out.println("After singing, the agent needs to arrange the return trip back");
                        return result + "--Nice to hear!Nice to hear";
                    }
                });
        System.out.println(proxy.sing("Clearly"));
    }

}

result:

You need to negotiate the performance fee with the agent before the performance
Obviously, he is gentle~~~
After singing, the agent needs to arrange the return trip back
It's -- it sounds good! Nice to hear

III CGLIB dynamic proxy

However, when the target object does not implement any interface, we can't use JDK dynamic proxy. Then we can only use CGLIB agent at this time. The essence of CGLIB is that its proxy class inherits the target object and overrides the related methods.

Create a target class VaeSingService without interface first:

public class VaeSingService {
    public String sing(String str) {
        if ("Why not".equals(str) ) {
            System.out.println("Sing this song for you~He has no style~Just means I want to give you happiness~");
            return str;
        }
        return "Can't sing~~~~";
    }
}

Create a CGLIB proxy class to implement the MethodInterceptor interface and override its intercept interface:

I use a generic approach here

public class CglibProxy<T> implements MethodInterceptor {
    //Target object
    T target;

    public CglibProxy(T taget) {
        this.target = taget;
    }

    public T creatTaget() {
        Enhancer enhancer = new Enhancer();
        //Specify parent class
        enhancer.setSuperclass(target.getClass());
        //Specify callback method
        enhancer.setCallback(this);
        //Create proxy object
        return (T) enhancer.create();
    }

    //Specific proxy methods to be executed
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        //What needs to be done before executing the target method
        System.out.println("You need to negotiate the performance fee with the agent before the performance");
        //Call the method of the target object
        String result = (String) method.invoke(target,objects);

        //What needs to be done after executing the target method
        System.out.println("After singing, the agent needs to arrange the return trip back");
        return result + "--Nice to hear!Nice to hear";
    }
}

testVae:

public class Test03 {
    public static void main(String[] args) {
        //Target object
        VaeSingService target = new VaeSingService();
        VaeSingService proxy = new CglibProxy<VaeSingService>(target).creatTaget();
        System.out.println(proxy.sing("Why not"));
    }
}

result:

You need to negotiate the performance fee with the agent before the performance
Sing this song for you ~ he has no style ~ it just means I want to give you happiness~
After singing, the agent needs to arrange the return trip back
Why not -- good! Nice to hear

testJay:

public class Test03 {
    public static void main(String[] args) {
        //Target object
//        VaeSingService target = new VaeSingService();
//        VaeSingService proxy = new CglibProxy<VaeSingService>(target).creatTaget();
        JaySingService target = new JaySingService();
        JaySingService proxy = new CglibProxy<JaySingService>(target).creatTaget();
//        System.out.println(proxy.sing("why not");
        System.out.println(proxy.sing("Flower Sea"));
    }
}

result:

You need to negotiate the performance fee with the agent before the performance
Don't you leave ~ distance is inseparable~
After singing, the agent needs to arrange the return trip back
Huahai -- good! Nice to hear

Topics: WPF linq p2p