Agent mode of design mode (20)

1, Foreword

        In some cases, a customer does not want or cannot directly access an object. At this time, it needs to find an intermediary to help complete a task. This intermediary is the proxy object. For example, you don't have to go to the railway station to buy train tickets. You can buy them through 12306 website or go to the train ticket agency. Another example is to find a girlfriend, a nanny, a job, etc. can be completed by looking for an intermediary.

        In software design, there are many examples of using proxy mode. For example, the remote object to be accessed is relatively large (such as video or large image), and its download takes a lot of time. In addition, for security reasons, it is necessary to shield the client from directly accessing real objects, such as the internal database of a unit.

2, Agent mode

        2.1 basic introduction of agent mode

        For some reasons, it is necessary to provide a proxy for an object to provide access control of the object. In fact, it is necessary to provide a substitute for an object to control access to the object. That is, the target object is accessed through the proxy object. The advantage of this sub operation is that additional function operations can be enhanced on the basis of the realization of the target object, that is, the function of the target object can be expanded.

        The proxied object can be a remote object, creating an expensive object or an object requiring security control.

        There are three kinds of proxy modes: static proxy, dynamic proxy (JDK proxy, interface proxy) and Cglib proxy (you can create objects in memory instead of dynamic proxy, so you need to implement interfaces).

        The schematic diagram of agent mode is as follows:  

          2.2. Static proxy

        2.2.1 basic introduction of static agent

        When using a static proxy, you need to define an interface or parent class. The proxy object (target object) and the proxy object implement together or inherit the same parent class.

        2.2.2 application examples

        Specific requirements:

  1.   Define an interface: ITeacherDao
  2. The target object TeacherDAO implements the interface ITeacherDAO
  3. Using the static proxy method, you need to implement ITeacherDAO in the proxy object TeacherDAOProxy
  4. When called, the target object is called by calling the method of the proxy object
  5. Special reminder: 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.

        The implementation class diagram is as follows:

        2.2.3 code implementation

public class Client {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //Create target object (proxied object)
        TeacherDao teacherDao = new TeacherDao();

        //Create a proxy object and pass the proxy object to the proxy object at the same time
        TeacherDaoProxy teacherDaoProxy = new TeacherDaoProxy(teacherDao);

        //Through the proxy object, call the method to the proxy object
        //That is, the method of the proxy object is executed, and the proxy object calls the method of the target object 
        teacherDaoProxy.teach();
    }

}

//Proxy object, static proxy
public class TeacherDaoProxy implements ITeacherDao {

    private ITeacherDao target; // Target object, aggregated through interface


    //constructor 
    public TeacherDaoProxy(ITeacherDao target) {
        this.target = target;
    }


    @Override
    public void teach() {
        // TODO Auto-generated method stub
        System.out.println("Start agent to complete some operations..... ");//method
        target.teach();
        System.out.println("Submit.....");//method
    }

}

public class TeacherDao implements ITeacherDao {

	@Override
	public void teach() {
		// TODO Auto-generated method stub
		System.out.println(" The teacher is teaching.....");
	}

}

//Interface
public interface ITeacherDao {
	
	void teach(); // Teaching methods
}

          2.2.4 advantages and disadvantages of static agent

         Advantages: the target function can be extended through the proxy object without modifying the function of the target object.

         Disadvantages: because the proxy object needs to implement the same interface as the target object, there will be many proxy classes. Once methods are added to the interface, both the target object and the proxy object must be maintained.

2.3 dynamic agent

        2.3.1 basic introduction of dynamic agent

  1. The proxy object does not need to implement the interface, but the target object must implement the interface, otherwise the dynamic proxy cannot be used.
  2. The generation of proxy object is to dynamically build proxy object in memory by using JDK API.
  3. Dynamic agent is also called JDK agent and interface agent.

        2.3.2 API for generating proxy objects in JDK

  1. Package of proxy class: java.lang.reflect.Proxy.
  2. The JDK implementation agent only needs to use the newProxyInstance method, but this method needs to receive three parameters. The complete writing method is:   
static Object newProxyInstance(ClassLoader loader, Class<?>[] 
interfaces,InvocationHandler h )

        2.3.3 application examples of dynamic agent

        Improve the static proxy example of the above example. The specific code is as follows:

public class Client {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //Create target object
        ITeacherDao target = new TeacherDao();

        //Create a proxy object for the target object, which can be converted to ITeacherDao
        ITeacherDao proxyInstance = (ITeacherDao) new ProxyFactory(target).getProxyInstance();

        // proxyInstance=class com.sun.proxy.$Proxy0 dynamically generates proxy objects in memory
        System.out.println("proxyInstance=" + proxyInstance.getClass());
		
        //The method of the target object is called through the proxy object
        //proxyInstance.teach();

        proxyInstance.sayHello(" tom ");
    }

}


public class ProxyFactory {

    //Maintain a target Object, Object
    private Object target;

    //Constructor to initialize the target
    public ProxyFactory(Object target) {

        this.target = target;
    }

    //Generate a proxy object for the target object
    public Object getProxyInstance() {

        //explain
		/*
		 *  public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
                                          
            //1. ClassLoader loader :  Specifies the class loader used by the current target object, and the method to get the loader is fixed
            //2. Class<?>[] interfaces: The interface type implemented by the target object, and use the generic method to confirm the type
            //3. InvocationHandler h : In event processing, when executing the method of the target object, the event processor method will be triggered, and the currently executed target object method will be passed in as a parameter
		 */
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(),
                new InvocationHandler() {

                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        // TODO Auto-generated method stub
                        System.out.println("JDK Agent start~~");
                        //The reflection mechanism calls the method of the target object
                        Object returnVal = method.invoke(target, args);
                        System.out.println("JDK Proxy submission");
                        return returnVal;
                    }
                });
    }


}


public class TeacherDao implements ITeacherDao {

    @Override
    public void teach() {
        // TODO Auto-generated method stub
        System.out.println(" The teacher is teaching.... ");
    }

    @Override
    public void sayHello(String name) {
        // TODO Auto-generated method stub
        System.out.println("hello " + name);
    }

}

//Interface
public interface ITeacherDao {

	void teach(); // Training Methods 
	void sayHello(String name);
}

      2.4Cglib agent

        2.4.1 basic introduction of glib

  1. Both static proxy and JDK proxy modes require the target object to implement an interface, but sometimes the target object is only a separate object and does not implement any interface. At this time, the target object subclass can be used to implement the proxy - this is Cglib proxy.

  2. Cglib agent is also called subclass agent. It constructs a subclass object in memory to expand the function of the target object. Some books also attribute cglib agent to dynamic agent.

  3. Cglib is a powerful high-performance code generation package. It can extend java classes and implement java interfaces at runtime. It is widely used by many AOP frameworks, such as Spring AOP, to implement method interception.

  4.   How to select proxy mode in AOP programming: 1. The target object needs to implement the interface and use JDK proxy; 2. The target object does not need to implement the interface and uses Cglib proxy;

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

        2.4.2 implementation steps of glib

  •         You need to import the jar file of cglib.

        

  • To dynamically build subclasses in memory, it should be noted that the proxy class cannot be marked with final, otherwise an error will be reported.
  • If the method of the target object is final or static, it will not be intercepted, that is, additional methods of the target object will not be executed.

2.4.3 application examples of glib

        The schematic diagram is as follows:

        The specific code is as follows:

// client
public class Client {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //Create target object
        TeacherDao target = new TeacherDao();
        //Gets the proxy object and passes the target object to the proxy object
        TeacherDao proxyInstance = (TeacherDao) new ProxyFactory(target).getProxyInstance();

        //Execute the method of the proxy object and trigger the concept method to call the target object
        String res = proxyInstance.teach();
        System.out.println("res=" + res);
    }

}

// The proxy object needs to implement the MethodInterceptor and give the methods in the implementation
public class ProxyFactory implements MethodInterceptor {

    //Maintain a target object
    private Object target;

    //Constructor, passing in an object to be represented
    public ProxyFactory(Object target) {
        this.target = target;
    }

    //Returns a proxy object: the proxy object of the target object
    public Object getProxyInstance() {
        //1. Create a tool class
        Enhancer enhancer = new Enhancer();
        //2. Set parent class
        enhancer.setSuperclass(target.getClass());
        //3. Set callback function
        enhancer.setCallback(this);
        //4. Create a subclass object, that is, a proxy object
        return enhancer.create();

    }


    //Overriding the intercept method will call the method of the target object
    @Override
    public Object intercept(Object arg0, Method method, Object[] args, MethodProxy arg3) throws Throwable {
        // TODO Auto-generated method stub
        System.out.println("Cglib proxy pattern ~~ start");
        Object returnVal = method.invoke(target, args);
        System.out.println("Cglib proxy pattern ~~ Submit");
        return returnVal;
    }

}


// The target object does not implement any interfaces
public class TeacherDao {

    public String teach() {
        System.out.println(" In the teacher's lecture, I am cglib Proxy, no need to implement interface ");
        return "hello";
    }
}

          Now that the proxy mode has been discussed, I suggest you take another look at the AOP source code analysis, which will deepen your understanding of Spring AOP. Click here to learn: AOP of Spring source code analysis (9) (Part 2)_ jokeMqc's blog - CSDN blog in spring AOP source code analysis Part 1 Spring source code analysis (8) AOP (Part 1)_ The CSDN blog of jokeMqc mainly analyzes what the EnableAspectJAutoProxy annotation has done for us, and then specifically analyzes what the AnnotationAwareAspectJAutoProxyCreator has done. At present, we can get the source code we have analyzed. He has mainly done two things: first, find out all the enhancers, and second, create proxy objects. Next, let's analyze how the proxy object calls the target method. 1, Background @ enablehttps://blog.csdn.net/jokeMqc/article/details/121350201

Keywords: Design Pattern Dynamic Proxy

Added by jowatkins on Tue, 30 Nov 2021 14:26:36 +0200