使用javaassist实现接口

javaassist

依赖

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

接口

public interface Person {
    boolean getBoolean();
    char getChar();
    byte getByte();
    short getShort();
    int getInt();
    float getFloat();
    double getDouble();
    long getLong();
    String getName();
    void setId();
    int add(int a, int b);
    Student getStudent(char[] vv);
    Student[] getStudents(char[] vv);
    Long getL();
    Double getD();
    MyEnum getMyEnum();
}

代码

import javassist.*;

import java.io.FileOutputStream;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Set;


public class AssistUtil {

    private static Set<String> set = new HashSet<>();

    static {
        set.add("byte");
        set.add("char");
        set.add("short");
        set.add("int");
        set.add("float");
        set.add("double");
        set.add("long");
        set.add("boolean");
    }

    /**
     * @param clazz
     * @return
     * @throws Exception
     */
    private static byte[] generateByteCode(Class clazz) throws Exception {
        ClassPool pool = ClassPool.getDefault();
        //此句要打开要不然SpringBoot中打成jar包可能不生效
        pool.insertClassPath(new ClassClassPath(AssistUtil.class));
        //创建代理类对象
        CtClass ctClass = pool.makeClass(getNewClassName(clazz));
        //获取代理对象的接口类
        CtClass interfaceClass = pool.getCtClass(clazz.getName());
        CtClass[] interfaces = new CtClass[]{interfaceClass};
        //设置代理类的接口
        ctClass.setInterfaces(interfaces);
        //代理类的所有方法
        CtMethod[] methods = interfaceClass.getDeclaredMethods();
        for (CtMethod method : methods) {
            String methodName = method.getName();
            /**
             * 新生成方法,保证和原方法一样,如果返回值不是基础类型 返回null
             */
            CtMethod cm = new CtMethod(method.getReturnType(), methodName, method.getParameterTypes(), ctClass);
            //根据返回值类型处理基础类型,float,double,long要特殊处理,没有返回值时直接return
            String returnType = cm.getReturnType().getName();
            if (set.contains(returnType)) {
                if ("float".equals(returnType)) {
                    cm.setBody("return 0F;");
                } else if ("double".equals(returnType)) {
                    cm.setBody("return 0D;");
                } else if ("long".equals(returnType)) {
                    cm.setBody("return 0L;");
                } else {
                    cm.setBody("return 0;");
                }
            } else if (!"void".equals(returnType)) {
                cm.setBody("return null;");
            } else {
                cm.setBody("return;");
            }
            ctClass.addMethod(cm);
        }
        byte[] code = ctClass.toBytecode();
        return code;
        /**
         *         此3句打开会在当前生成一个class文件
         *         FileOutputStream fos = new FileOutputStream(getNewClassName(clazz) + ".class");
         *         fos.write(code);
         *         fos.close();
         */

        /**
         *  生成一个Class对象 这里直接返回此class也是可以的
         *  Class aClass = ctClass.toClass();
         */

    }


    /**
     * 通过当前类加载器加载此类
     *
     * @param clazz
     * @return
     * @throws Exception
     */
    public static Class getInterfaceImpl(Class<?> clazz) throws Exception {
        byte[] code = generateByteCode(clazz);
        ClassLoader loader = Thread.currentThread().getContextClassLoader();
        Class cls = Class.forName("java.lang.ClassLoader");
        Method method = cls.getDeclaredMethod("defineClass", new Class[]{String.class, byte[].class, int.class, int.class});
        method.setAccessible(true);
        try {
            Object[] args = new Object[]{getNewClassName(clazz), code, 0, code.length};
            Class newClazz = (Class) method.invoke(loader, args);
            return newClazz;
        } finally {
            method.setAccessible(false);
        }
    }

    private static String getNewClassName(Class<?> clazz) {
        return clazz.getSimpleName() + "Impl";
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值