JDK dynamic proxy & CGLib dynamic proxy of dynamic proxy

JDK dynamic proxy

Core idea: By implementing all the interfaces of the proxied class, generating a bytecode file and then constructing a proxy object, constructing an instance of the proxied class by holding reflection, and then calling the method of the proxy class instance through invoke reflection to achieve acting.

Disadvantage: JDK dynamic proxy objects must implement one or more interfaces
write picture description here

flow chart

write picture description here

Knowledge point

  • JDK implementation of dynamic proxy requires implementation classes to define business methods through interfaces
  • The proxy classes generated by the JDK are named starting with "$Proxy"
  • The Method of the proxy class generated by the JDK proxy is initialized in the static static code block;
  • The proxy class package generated by the public interface is "com.sun.proxy";
  • JDK dynamic proxy needs to implement the InvocationHandler interface;

Code:

package com.quancheng;

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

public class DynamicProxy {
    public static void main(String[] args) {
        Student stu = new Student();
        CusInvocationHandler handler = new CusInvocationHandler(stu);
        Play instance = (Play) Proxy.newProxyInstance(stu.getClass().getClassLoader(), stu.getClass().getInterfaces(), handler);
        instance.play();
    }
}

class CusInvocationHandler implements InvocationHandler {
    private Object target;

    public CusInvocationHandler(Object object) {
        this.target = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.err.println("代理方法处理");
        return method.invoke(target, args);
    }
}

interface Play {
    void play();
}

class Student implements Play {

    @Override
    public void play() {
        System.err.println("student ====>");
    }
}

Example of generated proxy class:

import dynamic.proxy.UserService;  
import java.lang.reflect.*;  

public final class $Proxy11 extends Proxy  
    implements UserService  
{  

    // 构造方法,参数就是刚才传过来的MyInvocationHandler类的实例  
    public $Proxy11(InvocationHandler invocationhandler)  
    {  
        super(invocationhandler);  
    }  

    public final boolean equals(Object obj)  
    {  
        // 省略
    }  

    /** 
     * 被代理的方法 
     */  
    public final void add()  
    {  
        try  
        {  
            // 实际上就是调用MyInvocationHandler的public Object invoke(Object proxy, Method method, Object[] args)方法,第二个问题就解决了  
            super.h.invoke(this, m3, null);  
            return;  
        }  
        catch(Error _ex) { }  
        catch(Throwable throwable)  
        {  
            throw new UndeclaredThrowableException(throwable);  
        }  
    }  

    public final int hashCode()  
    {  
        // 省略
    }  

    public final String toString()  
    {  
        // 省略
    }  

    private static Method m1;  
    private static Method m3;  
    private static Method m0;  
    private static Method m2;  

    // 在静态代码块中获取了4个方法:Object中的equals方法、UserService中的add方法、Object中的hashCode方法、Object中toString方法  
    static   
    {  
        try  
        {  
            m1 = Class.forName("java.lang.Object").getMethod("equals", new Class[] {  
                Class.forName("java.lang.Object")  
            });  
            m3 = Class.forName("dynamic.proxy.UserService").getMethod("add", new Class[0]);  
            m0 = Class.forName("java.lang.Object").getMethod("hashCode", new Class[0]);  
            m2 = Class.forName("java.lang.Object").getMethod("toString", new Class[0]);  
        }  
        catch(NoSuchMethodException nosuchmethodexception)  
        {  
            throw new NoSuchMethodError(nosuchmethodexception.getMessage());  
        }  
        catch(ClassNotFoundException classnotfoundexception)  
        {  
            throw new NoClassDefFoundError(classnotfoundexception.getMessage());  
        }  
    }  
}

cglib dynamic proxy

Core idea: CGLib uses a very low-level bytecode technology. The principle is to create a subclass for a class through bytecode technology (the bottom layer of CGLib is a dynamic proxy implemented through inheritance), and use method interception technology in the subclass. Intercept all parent class method calls and weave in cross-cutting logic. Both JDK dynamic proxy and CGLib dynamic proxy are the basis for implementing Spring AOP; bottom layer: use a small and fast bytecode processing framework ASM (Java Bytecode Manipulation Framework) to convert bytecode and generate new classes

Disadvantage: Cannot proxy final-modified classes

Sample code:

//被代理的类即目标对象
public class A {
    public void execute(){
        System.out.println("执行A的execute方法...");
    }
}

//代理类
public class CGLibProxy implements MethodInterceptor {

    /**
     * 被代理的目标类
     */
    private A target;

    public CGLibProxy(A target) {
        super();
        this.target = target;
    }

    /**
     * 创建代理对象
     * @return
     */
    public A createProxy(){
        // 使用CGLIB生成代理:
        // 1.声明增强类实例,用于生产代理类
        Enhancer enhancer = new Enhancer();
        // 2.设置被代理类字节码,CGLIB根据字节码生成被代理类的子类
        enhancer.setSuperclass(target.getClass());
        // 3.//设置回调函数,即一个方法拦截
        enhancer.setCallback(this);
        // 4.创建代理:
        return (A) enhancer.create();
    }

    /**
     * 回调函数
     * @param proxy 代理对象
     * @param method 委托类方法
     * @param args 方法参数
     * @param methodProxy 每个被代理的方法都对应一个MethodProxy对象,
     *                    methodProxy.invokeSuper方法最终调用委托类(目标类)的原始方法
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
   //过滤不需要该业务的方法
      if("execute".equals(method.getName())) {
          //调用前验证权限(动态添加其他要执行业务)
          AuthCheck.authCheck();

          //调用目标对象的方法(执行A对象即被代理对象的execute方法)
          Object result = methodProxy.invokeSuper(proxy, args);

          //记录日志数据(动态添加其他要执行业务)
          Report.recordLog();

          return result;
      }else if("delete".equals(method.getName())){
          //.....
          return methodProxy.invokeSuper(proxy, args);
      }
      //如果不需要增强直接执行原方法
      return methodProxy.invokeSuper(proxy, args);

    }
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325675126&siteId=291194637