天天看点

动态代理实现原理

动态代理由来

Java程序员应该都知道,静态代理就是使用一个代理类(Proxy)来完成想要完成的事情,Proxy类通过编译器编译成class文件,当系统运行时,此class已经存在。这种静态的代理模式在增强现有的接口业务功能方面有很大的优点,但是大量使用静态代理,会使系统内的类大规模爆发,不易维护。

为了解决这个问题,就有了动态创建Proxy的想法,在运行状态中,动态的创建一个Proxy代理类,使用完之后就会销毁,这样就不用维护大量的代理类。

静态代理案例

创建一个车票接口,定义一个卖票的方法。

package com.doaredo.test.proxy;

public interface Ticket {
    public void sell();
}
           

创建一个车站类,实现卖票的接口,让其拥有卖票的功能。

package com.doaredo.test.proxy;

public class Station implements Ticket {
    @Override
    public void sell() {
        System.out.println("车站售票");
    }
}
           

创建一个售票代理类,实现车票接口,通过构造函数注入车站类,让其可以代理车站售票。

package com.doaredo.test.proxy;

public class StationProxy implements Ticket {
    private Station station;

    // 构造函数注入车站类,使其拥有售票功能
    public StationProxy(Station station){
        this.station = station;
    }

    @Override
    public void sell() {
        System.out.println("代理点开始售票");
        station.buy();
        System.out.println("代理点售票完成");
    }
}
           

创建测试类,使用售票代理类来完成售票。

package com.doaredo.test.proxy;

import sun.misc.ProxyGenerator;

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

public class Test {

    public static void main(String[] args) throws Exception {
        // 通过构造函数传入车站对象,使代理对象拥有售票功能
        StationProxy stationProxy = new StationProxy(new Station());
        stationProxy.sell();
    }

}
           

静态代理比较简单,代理类只需要实现目标类的接口,然后通过构造函数注入目标类,这样便可以完成目标类方法的调用,代理类可以在目标方法执行的前后做一些额外的功能,从而实现代理功能。

InvocationHandler的由来

代理就是在调用目标方法之前或者之后做一些额外的功能,但是我们在写完代理类后,还需要再去调用指定的目标方法,上面静态代理的目标方法为sell方法,这个目标方法是由我们自己定义的,不能统一。

为了构造出具有通用性和简单性的代理类,于是将调用目标方法统一交给一个管理器,让这个管理器统一的调用目标方法。这个管理器就是InvocationHandler。由于目标方法名称不同,怎么才能统一调用呢?在Java中使用反射就可以来实现统一的调用目标方法,将目标方法统一为反射中的Method。

JDK动态代理

使用JDK动态代理来实现本站售票的代理类。

创建一个车票接口,定义一个卖票的方法。

package com.doaredo.test.proxy;

public interface Ticket {
    public void sell();
}
           

创建一个车站类,实现卖票的接口,让其拥有卖票的功能。

package com.doaredo.test.proxy;

public class Station implements Ticket {
    @Override
    public void sell() {
        System.out.println("车站售票");
    }
}
           

创建InvocationHandler的实现类,通过构造函数注入目标类(即被代理的类,这里Station车站类将被代理)。

实现invoke方法,Method参数就是要执行的目标方法,通过method.invoke从而完成目标方法的调用,在目标方法调用的前后来完成代理功能。

package com.doaredo.test.proxy;

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

public class InvocationHandlerImpl implements InvocationHandler {
    private Station station;

    public InvocationHandlerImpl(Station station){
        this.station = station;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("jdk动态代理开始");
        method.invoke(station, args);
        System.out.println("jdk动态代理结束");
        return null;
    }
}
           

创建测试类,完成JDK动态代理的调用,同时将JDK动态生成的代理类的class文件输出。

  • 既然JDK要动态的帮我们生成代理类,动态的生成代理类后需要进行加载,所以需要一个类加载器ClassLoader。
  • 需要目标类实现的接口。(为什么要接口?)
  • 执行目标方法,完成代理功能的管理类,InvocationHandler的实现。
package com.doaredo.test.proxy;

import sun.misc.ProxyGenerator;

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

public class Test {

    public static void main(String[] args) throws Exception {
        Station station = new Station();
        // 类加载器
        ClassLoader classLoader = station.getClass().getClassLoader();
        // 接口信息
        Class[] interfaces = station.getClass().getInterfaces();
        // InvocationHandler的实现,完成代理功能,执行目标方法
        InvocationHandler handler = new InvocationHandlerImpl(station);
        // Jdk动态生成代理对象
        Object o = Proxy.newProxyInstance(classLoader,interfaces,handler);
        Ticket ticket = (Ticket)o;
        ticket.sell();
        generateClassFile(station.getClass(), "JdkProxyStation");
    }

    // 生成class文件
    public static void generateClassFile(Class clazz, String proxyName) throws Exception {
        byte[] bytes = ProxyGenerator.generateProxyClass(proxyName, clazz.getInterfaces());
        String path = clazz.getResource(".").getPath();
        FileOutputStream fos = new FileOutputStream(path + proxyName + ".class");
        fos.write(bytes);
        fos.flush();
        fos.close();
    }
}
           

使用Jdk动态代理,并生成动态产生的代理类的class文件,通过反编译查看生成的代码如下:

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

import com.doaredo.test.proxy.Ticket;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.lang.reflect.UndeclaredThrowableException;

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

    public JdkProxyStation(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);
        }
    }

    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 void sell() throws  {
        try {
            super.h.invoke(this, m3, (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"));
            m2 = Class.forName("java.lang.Object").getMethod("toString");
            m3 = Class.forName("com.doaredo.test.proxy.Ticket").getMethod("sell");
            m0 = Class.forName("java.lang.Object").getMethod("hashCode");
        } catch (NoSuchMethodException var2) {
            throw new NoSuchMethodError(var2.getMessage());
        } catch (ClassNotFoundException var3) {
            throw new NoClassDefFoundError(var3.getMessage());
        }
    }
}
           

我们可以看到,Jdk生成的代理类都继承了Proxy,同时实现了我们目标类的接口,其中m3就是要执行的目标方法。其它的都是Object类中的方法。我们看一下是怎么执行目标方法的:

super.h其实就是指的Proxy中的InvocationHandler,也就是在这里将m3传递给了InvocationHandler的invoke方法,从而可以通过m3来完成目标方法的调用。

平时我们看的资料都说Jdk动态代理只能是接口,这下大家都知道原因了吧,因为Java是单继承的,而Jdk动态代理中,Jdk自己已经继承了Proxy,所以我们不能再使用继承了,而只能使用接口的形式。

代理类特点:

  1. 继承自Proxy,实现了定义的接口
  2. 类中的所有方法都是final的
  3. 所有的方法实现都统一调用了InvocationHandler的invoke()方法

Cglib动态代理

Jdk提供的动态代理有个特点:某个类必须有实现的接口,而生成的代理类也只能代理接口定义的方法。也就是说,如果某个类没有实现接口,那么这个类就不能使用Jdk产生动态代理了。

Cglib可以在没有接口的情况下完成动态代理,原理差不多,后面我们自己来生成代理类实现代理功能。

下面是Cglib的使用:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>idea-demo</groupId>
    <artifactId>idea-demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <!--sm包 -->
        <dependency>
            <groupId>org.ow2.asm</groupId>
            <artifactId>asm</artifactId>
            <version>8.0.1</version>
        </dependency>
        <!-- cglib包 -->
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
             <version>3.3.0</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>
    
</project>
           
package com.doaredo.test.proxy;

public class CglibStation {

    public void sell() {
        System.out.println("车站售票");
    }

}
           
package com.doaredo.test.proxy;

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class CglibProxy implements MethodInterceptor {
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("cglib代理开始");
        methodProxy.invokeSuper(o, objects);
        System.out.println("cglib代理结束");
        return null;
    }
}
           
package com.doaredo.test.proxy;

import net.sf.cglib.proxy.Enhancer;
import sun.misc.ProxyGenerator;

import java.io.FileOutputStream;

public class Test {

    public static void main(String[] args) throws Exception {
        CglibStation cglibStation = new CglibStation();
        CglibProxy cglibProxy = new CglibProxy();
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(cglibStation.getClass());
        enhancer.setCallback(cglibProxy);
        CglibStation proxy = (CglibStation) enhancer.create();
        proxy.sell();
    }
}
           

更深层次理解动态代理

要明白动态代理,不能只是表面的怎么使用动态代理,记住一点,动态代理最重要的就是:动态的创建一个类,加入需要添加的逻辑代码,并且执行被代理对象的逻辑。

既然是动态的创建类,据我所知,操作Java常用的有Javassist和ASM,Javassist相对ASM使用上比较简单,下面就使用Javassist来学习动态代理模式是怎么实现的。

加入javassist依赖

<dependency>
    <groupId>org.javassist</groupId>
    <artifactId>javassist</artifactId>
    <version>3.21.0-GA</version>
</dependency>
           

定义接口

// 先定义一个接口
public interface Service {
    public void hello(String msg);
    public void bye(String name);
}
           

使用javassist动态创建类,注意:并非是代理类,是用javassist动态创建Service接口的实现类:

  • 创建一个ServiceImpl类,实现Service接口
  • 在实现类的hello方法中,输出hello+msg参数,在javassist中,$1表示第一个参数
package com.doaredo.test.proxy;

import javassist.*;
import org.junit.Test;

public class JavassistProxy {

    @Test
    public void test() throws Exception {
        ClassPool classPool = ClassPool.getDefault();
        // 创建一个类
        CtClass clazz = classPool.makeClass("ServiceImpl");
        // 获取定义的接口,转换成CtClass
        CtClass interfaceCtClass = classPool.get(Service.class.getName());
        // 给类添加接口
        clazz.addInterface(interfaceCtClass);
        // 逻辑代码
        String code = "{System.out.println(\"hello:\"+$1);}";
        // String类型的CtClass
        CtClass stringCtClass = classPool.get(String.class.getName());
        // 实现接口中的hello方法
        CtMethod hello = CtNewMethod.make(CtClass.voidType, "hello",
                new CtClass[]{stringCtClass},// 参数
                new CtClass[0],// 异常
                code,// 逻辑代码
                clazz);// 实现方法的类
        clazz.addMethod(hello);
        // 将CtClass转换成Java的Class
        Class cla = classPool.toClass(clazz);
        // 实例化Class执行对应的方法
        Service service = (Service) cla.newInstance();
        service.hello("doaredo");
    }
}
           

上面利用Javassist动态的创建了一个类,并且实现了Service接口的hello方法,但是有几个问题:

  • 获取定义接口的时候,Service.class.getName()是写死的,如果接口不叫Service那么就不好使了
  • 逻辑代码是通过手写的,编译器无法识别,容易出错

改进后代码如下:

  • 将接口和逻辑代码都通过参数形式传递进来
package com.doaredo.test.proxy;

import javassist.*;
import org.junit.Test;

public class JavassistProxy {

    public static <T> T createClass(Class<T> interfaceClass, String code) throws Exception {
        ClassPool classPool = ClassPool.getDefault();
        // 创建一个类
        CtClass clazz = classPool.makeClass("ServiceImpl");
        // 获取定义的接口,转换成CtClass
        CtClass interfaceCtClass = classPool.get(interfaceClass.getName());
        // 给类添加接口
        clazz.addInterface(interfaceCtClass);
        // String类型的CtClass
        CtClass stringCtClass = classPool.get(String.class.getName());
        CtMethod hello = CtNewMethod.make(CtClass.voidType, "hello",
                new CtClass[]{stringCtClass},// 参数
                new CtClass[0],// 异常
                code,// 逻辑代码
                clazz);// 实现方法的类
        clazz.addMethod(hello);
        // 实例化Class
        Class cla = classPool.toClass(clazz);
        return (T) cla.newInstance();
    }

    @Test
    public void test2() throws Exception {
        Service service = createClass(Service.class,"{System.out.println(\"hello:\"+$1);}");
        service.hello("doaredo");
        // 缺点:换方法后不能用了
        //service.bye("doaredo");
    }
}
           

经过改进后发现这里hello方法与是写死的,我们的目的是要能代理接口的所有方法,以及自定义逻辑代码。既然要自定义逻辑代码,那么就定义一个执行逻辑代码的接口,将逻辑代码以参数形式传递进来。

public interface InvocationHandler {
    Object invoke(String method, Object args[]);
}
           

接下来动态的实现接口中的所有的方法:

  • 创建接口的实现类
  • 给类添加InvocationHandler属性,通过InvocationHandler可以调用实现的逻辑代码
  • 遍历接口中所有的方法,并实现所有的方法,所有方法都调用InvocationHandler的invoke方法来执行代理逻辑以及目标方法
  • 将InvocationHandler实现类注入到handler属性中
  • $args是javassist中的语法,相当于Object args[]
package com.doaredo.test.proxy;

import javassist.*;
import org.junit.Test;

import java.lang.reflect.Method;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.stream.Collectors;

public class JavassistProxy {

	private static int count = 0;
    
    public static<T> T proxy(Class<T> interfaceClass, InvocationHandler h) throws Exception {
        ClassPool classPool = ClassPool.getDefault();
        // 创建一个类
        CtClass clazz = classPool.makeClass("&proxy&"+(count++)+"."+interfaceClass.getName());
        clazz.addInterface(classPool.get(interfaceClass.getName()));
        // 添加handler属性
        CtField ctField = CtField.make("public com.doaredo.test.proxy.JavassistProxy.InvocationHandler handler=null;", clazz);
        clazz.addField(ctField);
        // 遍历接口中的所有方法,并实现接口中的方法
        for (Method m : interfaceClass.getMethods()){
            // 获取方法的返回类型
            CtClass returnType = classPool.get(m.getReturnType().getName());
            // 获取方法名称
            String name = m.getName();
            // 获取方法参数
            CtClass[] parameters = ctClass(classPool, m.getParameterTypes());
            // 获取异常
            CtClass[] errors = ctClass(classPool, m.getExceptionTypes());
            String code = "";
            if(Void.class.equals(returnType)){
                // 没有返回值
                code = "this.handler.invoke(\"%s\", $args);";
            }else{
                code = "return ($r)this.handler.invoke(\"%s\", $args);";
            }
            // 实现接口中的方法
            CtMethod hello = CtNewMethod.make(returnType, name,
                    parameters,
                    errors,
                    String.format(code, m.getName()),
                    clazz);
            clazz.addMethod(hello);
        }
        // 将CtClass转换成Java的Class
        Class cla = classPool.toClass(clazz);
        // 实例化Class
        Object o = cla.newInstance();
        // 获取实例化类的handler属性,并且赋值为h。h为传入进来的逻辑代码实现类
        cla.getField("handler").set(o, h);

        // 将生成的类的代码写入到项目的target目录下
        byte[] bytes = clazz.toBytecode();
        Files.write(Paths.get(System.getProperty("user.dir") + "/target/" + clazz.getName() + ".class"), bytes);
        return (T) o;
    }

    private static CtClass[] ctClass(ClassPool cp, Class[] classes) {
        CtClass[] result = Arrays.stream(classes).map(c -> {
            try {
                return cp.get(c.getName());
            } catch (NotFoundException e) {
                e.printStackTrace();
            }
            return null;
        }).collect(Collectors.toList()).toArray(new CtClass[0]);
        return result;
    }
    
    @Test
    public void test3() throws Exception {
        Service service = proxy(Service.class, new InvocationHandler() {
            @Override
            public Object invoke(String method, Object[] args) {
                if(method.equals("hello")){
                    System.out.println("hello " + args[0]);
                }else if(method.equals("bye")){
                    System.out.println("bye " + args[0]);
                }
                return null;
            }
        });
        service.hello("doaredo");
        service.bye("doaredo");
    }

}
           

注意上面invoke方法中的method参数,是一个String类型,需要通过判断具体方法名称来决定具体的代理逻辑,显然不太合适,注意:上面只是利用Javassist动态的给Service接口创建了一个实现类,并没有给哪个类做代理。

下面我们稍微改造一下代码,来对具体的实现类进行动态代理:

package com.doaredo.test.proxy;

import javassist.*;
import org.junit.Test;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.stream.Collectors;

public class JavassistProxy {

    /**
     * 支持所有接口代理
     * 不直接传代码,容易出错
     */
    private static int count = 0;
    public static<T> T proxy(Class<T> interfaceClass, InvocationHandler h) throws Exception {
        ClassPool classPool = ClassPool.getDefault();
        // 创建一个类
        CtClass clazz = classPool.makeClass("&proxy&"+(count++)+"."+interfaceClass.getName());
        clazz.addInterface(classPool.get(interfaceClass.getName()));
        // 添加handler属性
        CtField ctField = CtField.make("public com.doaredo.test.proxy.JavassistProxy.InvocationHandler handler=null;", clazz);
        clazz.addField(ctField);
        // 遍历接口中的所有方法,并实现接口中的方法
        Method[] methods = interfaceClass.getMethods();
        for (int i = 0; i < methods.length; i++){
            Method m = methods[i];
            // 获取方法的返回类型
            CtClass returnType = classPool.get(m.getReturnType().getName());
            // 获取方法名称
            String name = m.getName();
            // 获取方法参数
            CtClass[] parameters = ctClass(classPool, m.getParameterTypes());
            // 获取异常
            CtClass[] errors = ctClass(classPool, m.getExceptionTypes());
            String code = "";
            String methodFieldTpl = "private static java.lang.reflect.Method %s=Class.forName(\"%s\").getDeclaredMethod(\"%s\", %s);";
            String classParams = "new Class[0]";
            if (m.getParameterTypes().length>0) {
                for (Class param : m.getParameterTypes()){
                    classParams = classParams.equals("new Class[0]") ? param.getName() + ".class" : classParams + "," + param.getName() + ".class";
                }
                classParams = "new Class[]{"+classParams+"}";
            }
            // 方法字段
            String methodFieldBody = String.format(methodFieldTpl, "m" + i, interfaceClass.getName(), m.getName(), classParams);
            // 为代理类添加反射方法字段
            CtField methodField=CtField.make(methodFieldBody,clazz);
            clazz.addField(methodField);

            if(Void.class.equals(returnType)){
                // 没有返回值
                // $0=this / $1,$2,$3... 代表方法参数
                code = "&0.handler.invoke("+methodField.getName()+", $args);";
            }else{
                code = "return ($r)this.handler.invoke("+methodField.getName()+", $args);";
            }
            // 实现接口中的方法
            CtMethod hello = CtNewMethod.make(returnType, name,
                    parameters,
                    errors,
                    String.format(code, m),
                    clazz);
            clazz.addMethod(hello);
        }
        // 将生成的类的代码写入到项目的target目录下
        byte[] bytes = clazz.toBytecode();
        Files.write(Paths.get(System.getProperty("user.dir") + "/target/" + clazz.getName() + ".class"), bytes);

        // 将CtClass转换成Java的Class
        Class cla = classPool.toClass(clazz);
        // 实例化Class
        Object o = cla.newInstance();
        // 获取实例化类的handler属性,并且赋值为h。h为传入进来的逻辑代码实现类
        cla.getField("handler").set(o, h);
        return (T) o;
    }

    private static CtClass[] ctClass(ClassPool cp, Class[] classes) {
        CtClass[] result = Arrays.stream(classes).map(c -> {
            try {
                return cp.get(c.getName());
            } catch (NotFoundException e) {
                e.printStackTrace();
            }
            return null;
        }).collect(Collectors.toList()).toArray(new CtClass[0]);
        return result;
    }

    @Test
    public void test3() throws Exception {
        Service service = proxy(Service.class, new InvocationHandlerImpl(new ServiceImpl()));
        service.hello("doaredo");
        service.bye("doaredo");
    }

    // 实现代理接口,完成代理逻辑
    public class InvocationHandlerImpl implements InvocationHandler {
        private Service service;

        public InvocationHandlerImpl(Service service) {
            this.service = service;
        }
        @Override
        public Object invoke(Method method, Object[] args) {
            try {
                System.out.println("代理前");
                // 通过反射执行被代理对象的方法
                method.invoke(service, args);
                System.out.println("代理后");
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
            return null;
        }
    }

    // 代理类接口
    public interface InvocationHandler {
        Object invoke(Method method, Object args[]);
    }

    // 服务接口
    public interface Service {
        public void hello(String msg);
        public void bye(String name);
    }

    // 服务实现
    public class ServiceImpl implements Service {

        @Override
        public void hello(String msg) {
            System.out.println("hello " + msg);
        }

        @Override
        public void bye(String name) {
            System.out.println("bye " + name);
        }
    }

}
           

下面就是使用Javassist来实现JDK的动态代理,反编译生成的代码如下:

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

package &proxy&0.com.doaredo.test.proxy;

import com.doaredo.test.proxy.JavassistProxy.InvocationHandler;
import com.doaredo.test.proxy.JavassistProxy.Service;
import java.lang.reflect.Method;

public class JavassistProxy$Service implements Service {
    public InvocationHandler handler = null;
    private static Method m0 = Class.forName("com.doaredo.test.proxy.JavassistProxy$Service").getDeclaredMethod("hello", String.class);
    private static Method m1 = Class.forName("com.doaredo.test.proxy.JavassistProxy$Service").getDeclaredMethod("bye", String.class);

    public void hello(String var1) {
        this.handler.invoke(m0, new Object[]{var1});
    }

    public String bye(String var1) {
        return (String)this.handler.invoke(m1, new Object[]{var1});
    }

    public JavassistProxy$Service() {
    }
}
           

初次看会觉得比较绕,前面Jdk生成的代理类跟我们自己生成的代理类原理都是一样的,但是Jdk中还生成了Object类中的所有方法,同时继承了Proxy类。