目录

  • 静态代理
  • 动态代理
  • JDK动态代理
  • cglib动态代理
  • 代码示例
  • 静态代理代码示例
  • JDK动态代理代码示例
  • JDK动态代理原理
  • 核心API
  • 生成的代理class文件
  • CGLIB动态代理代码示例
  • 代理接口示例
  • 代理类示例
  • 测试
  • CGLIB动态代理原理
  • 核心API
  • 生成的代理class
  • StockService$$EnhancerByCGLIB$$b62322fb$$FastClassByCGLIB$$46217eb2.class
  • StockService$$FastClassByCGLIB$$558e11c5.class
  • StockService$$EnhancerByCGLIB$$b62322fb.class
  • debug代码调用过程
  • MethodProxy#invokeSuper 流程
  • MethodProxy#invoke 流程
  • 正确使用MethodProxy#invoke方法

静态代理

只能代理某一特定类型的接口或类, 需要对于不同类型的接口或类写一个代理类

动态代理

JDK动态代理

可以代理不同类型的接口

cglib动态代理

可以代理不同类型的接口或类

代码示例

静态代理代码示例

/**
 *
 * 物流服务
 * @author: haibin.tang
 * @date: 2021/2/7
 */
public interface LogisticsService {
    /**
     * 发货
     * @param logisticsNo 快递单号
     */
    void delivery(String logisticsNo);

    /**
     * 签收
     * @param logisticsNo 单号
     */
    void signing(String logisticsNo);
}
/**
 *  物流具体实现
 * @author: haibin.tang
 * @date: 2021/2/7
 */
public class LogisticsServiceImpl implements LogisticsService {

    public void delivery(String logisticsNo) {
        System.out.println("快递发货, 快递单号 -->> " + logisticsNo);
    }

    public void signing(String logisticsNo) {
        System.out.println("快递签收, 快递单号 -->> " + logisticsNo);
    }
}
/**
 * @author: haibin.tang
 * @date: 2021/2/7
 */
public class Main {

    public static void main(String[] args) {
        LogisticsProxy logisticsProxy = new LogisticsProxy();
        logisticsProxy.delivery("P1001");
        logisticsProxy.signing("P1000");
    }
}

JDK动态代理代码示例

/**
 * @author: haibin.tang
 * @date: 2021/2/5
 */
public interface UserService {

    String create(String name);
}
/**
 * @author: haibin.tang
 * @date: 2021/2/5
 */
public class UserServiceImpl implements UserService {

    public String create(String name) {
        System.out.println("创建用户 " + name);
        return "create user ok";
    }
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * 动态代理类
 * <br/>
 * @author: haibin.tang
 * @date: 2021/2/5
 */
public class JdkDynamicProxy implements InvocationHandler {
    /**
     * 真实对象
     */
    private final Object target;

    public JdkDynamicProxy(Object target) {
        this.target = target;
    }

    /**
     * 最终生成的目标代理类会调用该方法
     * @param proxy  调用该方法的代理实例
     * @param method 要调用的目标方法
     * @param args 调用方法所需的参数
     * @return
     * @throws Throwable
     */
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("调用开始" + target.getClass().getName() + "#" + method.getName());
        return method.invoke(target, args);
    }
}
import sun.misc.ProxyGenerator;

import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Proxy;

/**
 * @author: haibin.tang
 * @date: 2021/2/5
 */
public class Main {

    public static void main(String[] args) {
        UserService userService = (UserService) Proxy.newProxyInstance(UserService.class.getClassLoader(), new Class[]{UserService.class}, new JdkDynamicProxy(new UserServiceImpl()));
        System.out.println(userService.create("小明"));
        System.out.println(userService.create("小红"));
        saveProxyClass2Disk("e://UserService$Proxy.class", new Class[] {UserService.class});
    }

    /**
     * 根据传入的class 生成代理类, 并且把class持久化到磁盘上
     * @param path  持久化路径
     * @param classes  动态生成的代理类需要实现的接口
     */
    public static void saveProxyClass2Disk(String path, Class[] classes){
        byte[] classFile = ProxyGenerator.generateProxyClass(path, classes);
        FileOutputStream fos = null;
        try {
            fos = new FileOutputStream(path);
            fos.write(classFile);
            fos.flush();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                fos.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

JDK动态代理原理

生成一个实现业务接口的class文件,内部通过委托给InvocationHanlder对象调用invoke方法

核心API

public interface InvocationHandler {
    /**
    * 代理方法,可以无侵入式的扩展真实方法调用前后的功能
    * proxy: 生成的代理对象实例
    * method: 调用真实类实例的方法
    * args: 调用真实类实例方法所需的参数
    * return: 真实方法的返回值,也可以返回其他的
    */
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}
/**
*  loader: 类加载器, 用于加载生成的代理class
*  interfaces: 生成的代理class需要实现的接口
*  h: 自定义实现的InvocationHandler类型接口的类实例,用于生成的代理类实例调用该接口定义的invoke方法
*/
java.lang.reflect.Proxy#newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)

生成的代理class文件

package e:..UserService$Proxy;

import com.nanxhs.proxy.jdk.UserService;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

public final class class extends Proxy implements UserService {
    private static Method m1;
    private static Method m3;
    private static Method m2;
    private static Method m0;

    public class(InvocationHandler var1) throws  {
        super(var1);
    }

    public final boolean equals(Object var1) throws  {
        try {
            return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }
/**
*  UserService接口的方法
*/
    public final String create(String var1) throws  {
        try {
            // 调用invocationhanlder的invoke方法
            return (String)super.h.invoke(this, m3, new Object[]{var1});
        } catch (RuntimeException | Error var3) {
            throw var3;
        } catch (Throwable var4) {
            throw new UndeclaredThrowableException(var4);
        }
    }

    public final String toString() throws  {
        try {
            return (String)super.h.invoke(this, m2, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    public final int hashCode() throws  {
        try {
            return (Integer)super.h.invoke(this, m0, (Object[])null);
        } catch (RuntimeException | Error var2) {
            throw var2;
        } catch (Throwable var3) {
            throw new UndeclaredThrowableException(var3);
        }
    }

    static {
        try {
            m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
            m3 = Class.forName("com.nanxhs.proxy.jdk.UserService").getMethod("create", Class.forName("java.lang.String"));
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}

CGLIB动态代理代码示例

引入jar包

<dependency>
   <groupId>cglib</groupId>
   <artifactId>cglib</artifactId>
   <version>3.2.5</version>
</dependency>

代理接口示例

/**
 * @author: haibin.tang
 * @date: 2021/2/5
 */
public interface OrderService {

    String create(String productName);
}
/**
 * @author: haibin.tang
 * @date: 2021/2/5
 */
public class OrderServiceImpl implements OrderService {

    public String create(String productName) {
        System.out.println("购买商品 -->> " + productName);
        return "create order success";
    }
}
import net.sf.cglib.proxy.InvocationHandler;

import java.lang.reflect.Method;

/**
 * cglib 代理接口
 * @author: haibin.tang
 * @date: 2021/2/5
 */
public class CgLibDynamicProxy implements InvocationHandler {

    private Object target;

    public CgLibDynamicProxy(Object target) {
        this.target = target;
    }

    public Object invoke(Object o, Method method, Object[] args) throws Throwable {
        System.out.println("调用开始" + target.getClass().getName() + "#" + method.getName());
        return method.invoke(target, args);
    }
}

代理类示例

/**
 * @author: haibin.tang
 * @date: 2021/2/5
 */
public class StockService {

    public int getStock() {
        System.out.println("获取库存调用");
        return 157;
    }
}
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * cglib代理class
 *
 * @author: haibin.tang
 * @date: 2021/2/5
 */
public class CglibMethodInterceptor implements MethodInterceptor {

    public Object getProxy(Class superClass) {
        Enhancer enhancer = new Enhancer();
        enhancer.setCallback(this);
        enhancer.setSuperclass(superClass);
        return enhancer.create();
    }

    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("调用开始" + obj.getClass().getName() + "#" + method.getName());
        return proxy.invokeSuper(obj, args);
    }
}

测试

import net.sf.cglib.core.DebuggingClassWriter;
import net.sf.cglib.proxy.Proxy;

/**
 * @author: haibin.tang
 * @date: 2021/2/5
 */
public class Main {

    public static void main(String[] args) {
        //将cglib生成的代理类输出到指定的目录
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY, "e://cglib_class");

        OrderService orderService = (OrderService) Proxy.newProxyInstance(CgLibDynamicProxy.class.getClassLoader(), new Class[]{OrderService.class}, new CgLibDynamicProxy(new OrderServiceImpl()));
        System.out.println(orderService.create("HUAWEI P20 旗舰版"));

        System.out.println("-------------------------------------------------------------------");

        CglibMethodInterceptor cglibMethodInterceptor = new CglibMethodInterceptor();
        StockService stockProxy = (StockService) cglibMethodInterceptor.getProxy(StockService.class);
        System.out.println(stockProxy.getStock());
    }
}

CGLIB动态代理原理

核心API

public interface MethodInterceptor extends Callback {
    /**
    * obj: Enhancer生成的动态代理类实例对象
    * method: 真实调用方法
    * args: 调用方法所需的参数
    * proxy: 
    */
    public Object intercept(Object obj, java.lang.reflect.Method method, Object[] args,
                               MethodProxy proxy) throws Throwable;
}
/**
* 用于生成class
*/
net.sf.cglib.proxy.Enhancer#create()
public class MethodProxy {
    /**
    * 调用obj对象指定的方法
    * obj: 被调用对象
    * args: 调用方法所需参数
    * 注意:当obj为MethodInterceptor#intercept 方法的第一个参数值的时候,这里会导致栈溢出,因为内部会出现死循环调用,具体为什么 往下面看
    */
	public Object invoke(Object obj, Object[] args) throws Throwable;
    /**
    * 调用obj对象指定的super方法
    * obj:被调用的对象
    * args: 调用方法所需参数
    */
    public Object invokeSuper(Object obj, Object[] args) throws Throwable;
}

生成的代理class

StockService$$EnhancerByCGLIB$$b62322fb$$FastClassByCGLIB$$46217eb2.class

package com.nanxhs.proxy.cglib;

import com.nanxhs.proxy.cglib.StockService..EnhancerByCGLIB..b62322fb;
import java.lang.reflect.InvocationTargetException;
import net.sf.cglib.core.Signature;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.reflect.FastClass;

public class StockService$$EnhancerByCGLIB$$b62322fb$$FastClassByCGLIB$$46217eb2 extends FastClass {
  .......省略
    public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
        b62322fb var10000 = (b62322fb)var2;
        int var10001 = var1;
        try {
            switch(var10001) {
            case 7:
                return new Integer(var10000.getStock());
            case 8:
                var10000.setCallback(((Number)var3[0]).intValue(), (Callback)var3[1]);
                return null;
			.....
            case 20:
                return new Integer(var10000.CGLIB$getStock$0());
            }
        } catch (Throwable var4) {
            throw new InvocationTargetException(var4);
        }

        throw new IllegalArgumentException("Cannot find matching method/constructor");
    }
    .....省略
}

StockService$$FastClassByCGLIB$$558e11c5.class

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.nanxhs.proxy.cglib;

import java.lang.reflect.InvocationTargetException;
import net.sf.cglib.core.Signature;
import net.sf.cglib.reflect.FastClass;

public class StockService$$FastClassByCGLIB$$558e11c5 extends FastClass {
  ......
    public Object invoke(int var1, Object var2, Object[] var3) throws InvocationTargetException {
        StockService var10000 = (StockService)var2;
        int var10001 = var1;
        try {
            switch(var10001) {
            case 0:
                return new Integer(var10000.getStock());
            case 1:
                return new Boolean(var10000.equals(var3[0]));
            case 2:
                return var10000.toString();
            case 3:
                return new Integer(var10000.hashCode());
            }
        } catch (Throwable var4) {
            throw new InvocationTargetException(var4);
        }

        throw new IllegalArgumentException("Cannot find matching method/constructor");
    }
........
}

StockService$$EnhancerByCGLIB$$b62322fb.class

package com.nanxhs.proxy.cglib;

import java.lang.reflect.Method;
import net.sf.cglib.core.ReflectUtils;
import net.sf.cglib.core.Signature;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Factory;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

public class StockService$$EnhancerByCGLIB$$b62322fb extends StockService implements Factory {
    ....省略
        //调用父级的业务代码方法---MethodProxy#invokeSuper 方法最终调用
    final int CGLIB$getStock$0() {
        return super.getStock();
    }

    //调用本对象实现的业务代码方法----MethodProxy#invoke方法最终调用,所以这里会导致栈溢出
    public final int getStock() {
        MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
        if (var10000 == null) {
            CGLIB$BIND_CALLBACKS(this);
            var10000 = this.CGLIB$CALLBACK_0;
        }

        if (var10000 != null) {
            //导致栈溢出的根源,var10000的实际类型是MethodInterceptor, 调用他自己的intercept方法,intercept方法内部又调用MethodProxy#invoke方法,最终造成了死循环
            Object var1 = var10000.intercept(this, CGLIB$getStock$0$Method, CGLIB$emptyArgs, CGLIB$getStock$0$Proxy);
            return var1 == null ? 0 : ((Number)var1).intValue();
        } else {
            return super.getStock();
        }
    }
    .....省略
}

debug代码调用过程

MethodProxy#invokeSuper 流程

java 快递单号 正则表达式 jdk快递单号_java 快递单号 正则表达式

java 快递单号 正则表达式 jdk快递单号_java 快递单号 正则表达式_02

java 快递单号 正则表达式 jdk快递单号_java 快递单号 正则表达式_03

java 快递单号 正则表达式 jdk快递单号_动态代理_04

MethodProxy#invoke 流程

java 快递单号 正则表达式 jdk快递单号_System_05

java 快递单号 正则表达式 jdk快递单号_System_06

java 快递单号 正则表达式 jdk快递单号_动态代理_07

正确使用MethodProxy#invoke方法

解决invoke导致的栈溢出

java 快递单号 正则表达式 jdk快递单号_java 快递单号 正则表达式_08

为什么这样就不会栈溢出?

java 快递单号 正则表达式 jdk快递单号_java 快递单号 正则表达式_09

java 快递单号 正则表达式 jdk快递单号_动态代理_10