Spring learning 04 --- reflection, static proxy, dynamic proxy

Keywords: Java Spring

Write in front: the proxy mode can add new functions without changing the originally written function classes. The difficulty of dynamic agent lies in the implementation of reflection mechanism, so it is necessary to understand the reflection mechanism.

catalogue

1. Introduction to agency model

1.1 role of using agent mode

1.2 ways to implement agent mode

1.3 case model

2. Static proxy implementation

2.1 create Student interface

  2.2 student core business implementation class StudentImpl

2.3 student static agent class

  2.4 testing

3. Reflection

3.1 reflection cases

3.2 case analysis

4. Dynamic agent implementation

4.1jdk dynamic agent

4.2 code demonstration

4.3Cglib dynamic agent

4.4cglib code test

5. Summary

1. Introduction to agency model

1.1 role of using agent mode

         1. Function enhancement: additional functions are added to the original functions.

         2. Control enhancement: the agent class does not allow you to access the target, for example, the merchant does not allow users to access the manufacturer.

1.2 ways to implement agent mode

1. Static agent:

  (1) The proxy class is implemented manually. Create a java class to represent the proxy class.

  (2) At the same time, the target class you want to delegate should be determined.

Creation process:

  1. Create an interface (core function)
  2. Create implementation classes (methods that implement interfaces)
  3. Create a proxy class (you can also add your own methods to implement the interface)
  4. Create client class (test)

Advantages: simple code and easy implementation.

Disadvantages: when the functions in the interface are added or modified, many implementation classes will be affected and need to be modified. The workload will increase and the impact will be relatively large.

2. Dynamic agent:

When you modify the method in the interface, it will not affect the proxy class.

During the execution of the program, the jdk reflection mechanism is used to create the proxy class object and dynamically specify the target class to proxy.

There are two implementation methods:

  • The first is jdk dynamic proxy: use the classes and interfaces in java reflection package to realize the function of dynamic proxy. The jdk method can only be used if it has an interface. It can't be used without an interface. In this case, the cglib method should be considered.
  • The second is cglib dynamic proxy: cglib is a tool library provided by a third party to create proxy objects. The principle of cglib is inheritance. Cglib creates its subclass by inheriting the target class, and rewrites the method with the same name in the parent class in the subclass to modify the function.

Steps to implement dynamic proxy:

  • 1. Create an interface and define the functions to be completed by the target class
  • 2. Create the target class to implement the interface
  • 3. Create InvocationHandler interface implementation class and complete the function of proxy class in invoke method
  • 4. Use the static method of Proxy class to create Proxy object and convert the return value to interface type.

1.3 case model

Analysis: the methods of the core category: classroom study and homework. Other methods are non core business and belong to additional business.

2. Static proxy implementation

2.1 create Student interface

Student core business:

public interface Student {
    public void study();
    public void homework();
}

  2.2 student core business implementation class StudentImpl

Students' core business realization class to realize students' core business. Personal understanding: the so-called student implementation class is a polymorphism. Student is an abstract concept, and the class that implements it is a concrete thing. For example, Zhang San and Li Si are both students, so they should do what students must do (core business).

 
public class StudentImpl implements Student{
    //Core business: study and homework
    //Non core business: prepare for class, listen to the teacher, finish class, prepare for homework, start homework and finish homework
    @Override
    public void study() {
        System.out.println("Student learning----------------------");
    }
    @Override
    public void homework() {
        System.out.println("Students do their homework-------------------------");
    }
}

2.3 student static agent class

It is required that the student implementation class cannot be changed. In order to add non core business methods to the implementation class, create a static proxy class, StudentProxy, inherit the student class (equivalent to representing a student), and then rewrite the core business. Let's assume that Zhang San found a learning agent. The learning agent already has the students' core business (study and home work). Now the agent only needs to take Zhang San's study and home work (the agent calls Zhang San's method), so it doesn't change what Zhang San wants to do. The agent also has other additional businesses, such as preview, taking notes, picking up garbage, doing homework, reviewing and sorting schoolbags. At this point, you only need to add it to the core business.

//Student function agent class
public class StudentProxy implements Student{
    private Student student;
    public void setStudent(Student student) {
        this.student = student;
    }
    @Override
    public void study() {
        student.study();
        openBook();
        lectures();
        classOver();
    }
    @Override
    public void homework() {
        student.homework();
        proDoHomework();
        DoHomework();
        HomeworkOver();
    }
    //Add non core features
    //Non core business: prepare for class, listen to the teacher, finish class, prepare for homework, start homework and finish homework
    public void openBook(){
        System.out.println("Students open books to preview....");
    }
    public void lectures(){
        System.out.println("Students listen to the teacher, take notes and complete classroom exercises....");
    }
    public void classOver(){
        System.out.println("After class, students pack their schoolbags and take away the garbage..");
    }
    public void proDoHomework(){
        System.out.println("The students are going to do their homework and review what they have learned in today's class..");
    }
    public void DoHomework(){
        System.out.println("Students open their exercise books, do their homework, check and correct mistakes, and preview..");
    }
    public void HomeworkOver(){
        System.out.println("Students finish their homework, pack their books...");
    }
}

  2.4 testing

In the past, students called methods themselves, but now they find agents to complete student business.

public class StudentLiuSir {
    public static void main(String[] args) {
            //Static proxy mode
            //The static proxy class is equivalent to rewriting the core class, so the code reuse is too high and the development efficiency is low
            StudentImpl student=new StudentImpl();
            StudentProxy proxy = new StudentProxy();
            proxy.setStudent(student);
            proxy.study();
            proxy.homework();
   }
}

3. Reflection

3.1 reflection cases

To understand dynamic agents, you must understand some knowledge of reflection. Because the underlying layer of reflection is too complex, you only need to understand the basic methods and mechanisms.

 

3.2 case analysis

The jdk provides the Method class in the reflection package. This class can obtain the target class object through the Method name in the target class

Target class. Class. Getmethod (Method name, parameter type); You can get a Method Object. This Object has an invoke () Method, two parameters invoke (target Object, Method execution parameter value), and the return value is an Object type.

The target object here is the implementation class object declared in advance. After running, you get the result of "Hello, Li Si".

4. Dynamic agent implementation

4.1jdk dynamic agent

1. Reflection: Mehtod class, representation Method, Method in class. A Method can be executed through Method.

2. Implementation of JDK dynamic agent:

The reflection package java.lang.reflect contains three classes: invocationhandler, method and proxy

(1) InvocationHandler interface: just one method, invoke (), indicates what you want to do.

         invoke(): indicates the function code to be executed by the proxy object. The function to be completed by your proxy class is written in the invoke() method.

        Functions completed by proxy class:

  •                 Call the target method to perform the function of the target method.
  •                 Function enhancement: when the target method is called, the function is enhanced.

                Method prototype: public object invoke (object proxy, method, object [] args)

Parameter: Object proxy: the proxy object created by jdk. No assignment is required.

        Method: the method in the target class, and the method object provided by jdk.

        object[] args: parameter of the method in the target class, provided by jdk.

How to use: 1. Create a class to implement this interface invocationHandler

              2. Rewrite the invoke method to write the functions to be completed by the proxy class in the original static proxy.

(2) Method class: represents the method in the target class.

        Function: the method of a target class can be executed through method, method.invoke(); The invoke here just happens to have the same name as the invocationHandeler and is not related.

method.invoke (target object, method parameter);

(3) Proxy class: the core object. The proxy object is created. The previously created objects are the construction methods of new class;

Now use the method of proxy class instead of new.

Method: static method newproxyInstance()

The purpose is to create proxy objects.

Parameters: 1. Classloader class loader, which is responsible for loading objects into the class, uses the reflection mechanism to obtain the classLoder class a of the object, a.getClass().getClassLoder, and the class loader of the target object.

2.Class<?> [] interfaces interface, class loader of target object

3.InvocationHandler h: the functions to be completed by the proxy class written by ourselves.

Return value: the proxy object. (these three parameters process a proxy object for this target)

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

Steps to implement dynamic proxy:

  • 1. Create an interface and define the functions to be completed by the target class
  • 2. Create the target class to implement the interface
  • 3. Create InvocationHandler interface implementation class and complete the function of proxy class in invoke method
  • 4. Use the static method of Proxy class to create Proxy object and convert the return value to interface type.

  PS: Although the invoke method in the method and the invoke method in the invocationHandler class have the same name, there is no relationship, but they happen to have the same name.

4.2 code demonstration

The proxy processor, StudentProxyDTJdk, cannot be completely called a proxy class. It should be understood as a program processing section that can generate a proxy class. A proxy class will be generated only after the implementation class object is passed in and the getProxy () method is called.

package com.liu.demo1;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class StudentProxyDTJdk implements InvocationHandler {
    //Proxy interface
    private Object target;
    public void setStudent(Object target) {
        this.target = target;
    }
    //Generate the proxy class < class loader (loaded to that location), the interface of the proxy class, the proxy handler implementation class, that is, this >
    public Object getProxy(){
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Object result=null;
        if(method.getName().equals("study")){
            result = method.invoke(target, args);
            openBook();
            lectures();
            classOver();
        }
        if(method.getName().equals("homework")){
            result = method.invoke(target, args);
            proDoHomework();
            DoHomework();
            HomeworkOver();
        }
        return result;
    }
    public void openBook(){
        System.out.println("Students open books to preview....");
    }
    public void lectures(){
        System.out.println("Students listen to the teacher, take notes and complete classroom exercises....");
    }
    public void classOver(){
        System.out.println("After class, students pack their schoolbags and take away the garbage..");
    }
    public void proDoHomework(){
        System.out.println("The students are going to do their homework and review what they have learned in today's class..");
    }
    public void DoHomework(){
        System.out.println("Students open their exercise books, do their homework, check and correct mistakes, and preview..");
    }
    public void HomeworkOver(){
        System.out.println("Students finish their homework, pack their books...");
    }
}

  Test class: create the object of the target class and the object of the proxy class, throw the object of the target class to the handler, generate the dynamic proxy class object, and then use this object to call the student business. That is, after

proxyJdk.setStudent(student); And Student proxy = (Student) proxyJdk.getProxy(); after

Get the proxy object.

            StudentImpl student=new StudentImpl();
            StudentProxyDTJdk proxyJdk = new StudentProxyDTJdk();
            proxyJdk.setStudent(student);
            Student proxy = (Student) proxyJdk.getProxy();
            proxy.study();
            proxy.homework();

ps:jdk can only proxy interfaces. If the project has no interfaces, this method cannot be used. In this case, cglib should be considered.

4.3Cglib dynamic agent

      JDK needs to implement classes to define business methods through interfaces. For classes without interfaces, how to implement dynamic agents? This requires CGLib. CGLib adopts very low-level bytecode technology. Its principle is to create a subclass for a class through bytecode technology, and use the method interception technology in the subclass to intercept the calls of all parent class methods, so as to weave cross cutting logic. JDK dynamic proxy and CGLib dynamic proxy are the basis for implementing Spring AOP.

        Cglib is essentially an inheritance override, so it can be proxied as long as it is not a final class. When using, you need to guide the package.

         To implement the CGLIB dynamic proxy, you must implement the methodinterceptor interface

This interface has only one intercept() method, which has four parameters:

  • 1) o represents an enhanced object, that is, an object implementing this interface class;
  • 2) Method indicates the method to be intercepted;
  • 3) objects indicates the parameters of the method to be intercepted;
  • 4) methodproxy represents the method object to trigger the parent class;
package com.liu.demo1;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class StudentProxyDTCglib implements MethodInterceptor {
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        Object result=null;
        if(method.getName().equals("study")){
            result = methodProxy.invokeSuper(o, objects);
            openBook();
            lectures();
            classOver();
        }
        if(method.getName().equals("homework")){
            result = methodProxy.invokeSuper(o, objects);
            proDoHomework();
            DoHomework();
            HomeworkOver();
        }
        return result;
    }
    public void openBook(){
        System.out.println("Students open books to preview....");
    }
    public void lectures(){
        System.out.println("Students listen to the teacher, take notes and complete classroom exercises....");
    }
    public void classOver(){
        System.out.println("After class, students pack their schoolbags and take away the garbage..");
    }
    public void proDoHomework(){
        System.out.println("The students are going to do their homework and review what they have learned in today's class..");
    }
    public void DoHomework(){
        System.out.println("Students open their exercise books, do their homework, check and correct mistakes, and preview..");
    }
    public void HomeworkOver(){
        System.out.println("Students finish their homework, pack their books...");
    }
}

4.4cglib code test

         Enhancer is a very important class. It allows you to create a JAVA proxy for non interface types. Enhancer dynamically creates subclasses of a given class and intercepts all methods of the proxy class. Unlike JDK dynamic proxy, it can work normally regardless of the interface or class.

        StudentProxyDTCglib cglibProxy = new StudentProxyDTCglib();
        Enhancer enhancer = new Enhancer();
        //Set proxy target
        enhancer.setSuperclass(StudentImpl.class);
        //Set a single callback object to intercept the call to the target method in the call
        enhancer.setCallback(cglibProxy);
        //Set class loader
        enhancer.setClassLoader(StudentImpl.class.getClassLoader());
        Student student = (Student) enhancer.create();
        student.study();
        student.homework();

5. Summary

        Both static agent and dynamic agent have their own advantages. When there are few implementation classes, it will be more convenient to use static agent. When there are many target classes, the advantages of dynamic agent are reflected. If the target class is often modified and updated, the cumbersome operation of repeated modification can be avoided by using dynamic agent, so it is best to master the method of dynamic agent, so as to avoid more repeated operations.

Posted by prem on Thu, 11 Nov 2021 12:19:02 -0800