Shang Silicon Valley design pattern learning (13) -- [proxy -- Static proxy, dynamic proxy, Cglib proxy]

Gateway = = > Java design pattern of station B

❤❤❤ Thanks to Shang Silicon Valley ❤❤❤

Recently, I began to plan to learn design patterns. Come on!!!

proxy pattern

Proxy mode: provide a copy to an object, and control the access of the real object through the copy object. Even if you want to expand new content or functions, you can modify them on the copy object
(it can be understood as separation. You can find the ontology through separation. The management operation of separation will affect the ontology.)

The proxied object can be a remote object, an object with high creation cost, or an object requiring security control

It can be divided into three types:

Static proxy
Dynamic agent (JDK agent, interface agent)
Cglib agent (creating objects dynamically in memory)

Static proxy

The proxy object and the target object should implement the same interface, and then call the method of the target object by calling the same method.

Use static proxy mode; The target function can be extended through the proxy object without modifying the function of the target object;
However, because the proxy object needs to implement the same interface as the target object, many proxy classes need to be generated;
If the interface needs to add methods, both the target object and the proxy object need to add method implementations

Case:

Common interface between agent and target UserDao

//Interface, target object and proxy object should be implemented;
public interface UserDao {
    //Add user method;
    public abstract void addUser();
}

Target RealUserDao

//Objectives;
public class RealUserDao implements UserDao{
    @Override
    public void addUser() {
        System.out.println("The target object says you want to add users");
    }
}

Proxy ProxyUserDao

//Agency;
public class ProxyUserDao implements UserDao{

    //Aggregate goals;
    private UserDao target;

    public ProxyUserDao(UserDao target) {
        this.target = target;
    }

    @Override
    public void addUser() {
        System.out.println("Static proxy start-->");
        target.addUser();
        System.out.println("end--->");
    }
}

Impersonate Client

public class Client {
    public static void main(String[] args) {

        ProxyUserDao proxyUserDao =new ProxyUserDao(new RealUserDao());

        //Call the method to the target object through the proxy object;
        proxyUserDao.addUser();
    }
}

/*
Static proxy start -- >
The target object says you want to add users
 End -- >
*/

Dynamic agent

Only the target object needs to implement the interface; Proxy objects do not need to implement interfaces

Package of proxy class: java.lang.reflect.Proxy

The proxy object uses the JDK API to dynamically build the proxy object in memory;
When using the method newProxyInstance(),

Parameter: classloader; Specify the class loader used by the current target object;
Parameter: class <? > [] interfaces: the interface implemented by the target object
Parameter: InvocationHandler h) when executing the target object method, the event generator will be triggered, and the executed target object method will be obtained through reflection

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

Interface UserDao

//The interface only needs to be implemented by the target object;
public interface UserDao {
    //Add user method;
    public abstract void addUser();
}

Target class RealUserDao

//Objectives;
public class RealUserDao implements UserDao{
    @Override
    public void addUser() {
        System.out.println("The target object says you want to add users");
    }
}

proxy class

//Agent factory;
public class ProxyFactory {

    //Maintain target objects;
    private Object target;

    //initialization;
    public ProxyFactory(Object target) {
        this.target = target;
    }

    //Dynamic agent;
    public  Object getProxyInstance(){

        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("Dynamic agent/JDK agent");
                        Object invoke = method.invoke(target, args);
                        return invoke;
                    }
                });
    }
}

Simulation client

public class Client {

    public static void main(String[] args) {

        //Create the target object;
        UserDao realUserDao = new RealUserDao();

        //Create a proxy object for the target object;
        UserDao proxyFactory= (UserDao)new ProxyFactory(realUserDao).getProxyInstance();

        proxyFactory.addUser();
    }
}

/*
Dynamic agent / JDK agent
 The target object says you want to add users
*/

Cglib agent

Cglib agent (subclass agent)
Build a subclass object in memory; Realize the function expansion of the target object

Cglib Encyclopedia

The bottom layer of Cglib package is to convert bytecode and generate new classes by using bytecode processing framework ASM

Note that the class of the proxy cannot be defined as final, or an error is reported: java.lang.IllegalArgumentException:
If the method of the target object is final/static, it will not be intercepted (additional business methods of the target object will not be executed)

maven dependency required;

 <!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>3.2.11</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.ow2.asm/asm-commons -->
<dependency>
    <groupId>org.ow2.asm</groupId>
    <artifactId>asm-commons</artifactId>
    <version>7.1</version>
</dependency>

Class diagram principle

The getInstance () method creates a proxy object for the target object target;
The overridden intercept () method implements the method call to the target object

Target class RealUserDao

//Target class;
public class RealUserDao {
    //Add users;
    public  void addUser(){
        System.out.println("Yes Cglib The way,No interface required");
        System.out.println("How to add users");
    }
}

Proxy class ProxyFactory

//Agency;
public class ProxyFactory implements MethodInterceptor {
    //Define the target object;
    private Object target;

    //initialization;
    public ProxyFactory(Object target) {
        this.target = target;
    }

    //Returns the proxy object of target;
    public Object getProxyInstance(){
        //Create a tool class;
        Enhancer enhancer = new Enhancer();
        //Set parent class;
        enhancer.setSuperclass(target.getClass());
        //Set callback function;
        enhancer.setCallback(this);
        //Return the proxy object;
        return enhancer.create();
    }


    //The overridden intercept () method implements the method call to the target object
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("start Cglib proxy pattern");

        Object invoke = method.invoke(target, objects);
        System.out.println("Cglib proxy pattern==> Submit  <==");
        return invoke;
    }
}

Simulation client

//Simulation client;
public class Client {
    public static void main(String[] args) {
        //Target object;
        RealUserDao target =new RealUserDao();

        //Get the proxy object of the target object;
        RealUserDao proxyFactory = (RealUserDao) new ProxyFactory(target).getProxyInstance();
        //Method of executing proxy object;
        proxyFactory.addUser();
    }
}

/*

Start Cglib proxy mode
 Cglib mode is used, and no interface is required
 How to add users
Cglib Proxy mode = = > submit<==

*/

Keywords: Design Pattern

Added by axnoran on Tue, 28 Sep 2021 20:58:21 +0300