diff --git a/src/org/redkale/service/CacheSourceService.java b/src/org/redkale/service/CacheSourceService.java index e64f0e87e..0b2c6a147 100644 --- a/src/org/redkale/service/CacheSourceService.java +++ b/src/org/redkale/service/CacheSourceService.java @@ -104,23 +104,7 @@ public class CacheSourceService implements CacheSource, Service { File store = new File(home, "cache/" + name()); if (!store.isFile() || !store.canRead()) return; LineNumberReader reader = new LineNumberReader(new FileReader(store)); - final ParameterizedType storeType = new ParameterizedType() { - @Override - public Type[] getActualTypeArguments() { - return new Type[]{storeKeyType, storeValueType}; - } - - @Override - public Type getRawType() { - return CacheEntry.class; - } - - @Override - public Type getOwnerType() { - return null; - } - - }; + final Type storeType = TypeToken.createParameterizedType(CacheEntry.class, storeKeyType, storeValueType); String line; while ((line = reader.readLine()) != null) { if (line.isEmpty()) continue; @@ -148,23 +132,7 @@ public class CacheSourceService implements CacheSource, Service { store.getParentFile().mkdirs(); PrintStream stream = new PrintStream(store, "UTF-8"); Collection values = container.values(); - final ParameterizedType storeType = new ParameterizedType() { - @Override - public Type[] getActualTypeArguments() { - return new Type[]{storeKeyType, storeValueType}; - } - - @Override - public Type getRawType() { - return CacheEntry.class; - } - - @Override - public Type getOwnerType() { - return null; - } - - }; + final Type storeType = TypeToken.createParameterizedType(CacheEntry.class, storeKeyType, storeValueType);; for (CacheEntry entry : values) { stream.println(convert.convertTo(storeType, entry)); } diff --git a/src/org/redkale/util/Creator.java b/src/org/redkale/util/Creator.java index 4d6c58c25..ceac35ba7 100644 --- a/src/org/redkale/util/Creator.java +++ b/src/org/redkale/util/Creator.java @@ -8,8 +8,8 @@ import java.beans.ConstructorProperties; import java.lang.reflect.*; import java.util.*; import jdk.internal.org.objectweb.asm.*; -import static jdk.internal.org.objectweb.asm.Opcodes.*; import jdk.internal.org.objectweb.asm.Type; +import static jdk.internal.org.objectweb.asm.Opcodes.*; /** * 实现一个类的构造方法。 代替低效的反射实现方式。 不支持数组类 diff --git a/src/org/redkale/util/TypeToken.java b/src/org/redkale/util/TypeToken.java index 7c4c48aef..0a2525234 100644 --- a/src/org/redkale/util/TypeToken.java +++ b/src/org/redkale/util/TypeToken.java @@ -6,9 +6,11 @@ package org.redkale.util; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; +import jdk.internal.org.objectweb.asm.*; +import static jdk.internal.org.objectweb.asm.Opcodes.*; /** - * + * * 获取泛型的Type类 * * @see http://www.redkale.org @@ -26,4 +28,52 @@ public abstract class TypeToken { public final Type getType() { return type; } + + public static Type createParameterizedType(final Class rawType, final Class... actualTypeArguments) { + ClassLoader loader = TypeToken.class.getClassLoader(); + String newDynName = TypeToken.class.getName().replace('.', '/') + "_Dyn" + System.currentTimeMillis(); + for (;;) { + try { + Class.forName(newDynName.replace('/', '.')); + newDynName = TypeToken.class.getName().replace('.', '/') + "_Dyn" + Math.abs(System.nanoTime()); + } catch (Exception ex) { //异常说明类不存在 + break; + } + } + ClassWriter cw = new ClassWriter(0); + FieldVisitor fv; + MethodVisitor mv; + cw.visit(V1_8, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynName, null, "java/lang/Object", null); + String rawTypeDesc = jdk.internal.org.objectweb.asm.Type.getDescriptor(rawType); + StringBuilder sb = new StringBuilder(); + sb.append(rawTypeDesc.substring(0, rawTypeDesc.length() - 1)).append('<'); + for (Class c : actualTypeArguments) { + sb.append(jdk.internal.org.objectweb.asm.Type.getDescriptor(c)); + } + sb.append(">;"); + { + fv = cw.visitField(ACC_PUBLIC, "field", rawTypeDesc, sb.toString(), null); + fv.visitEnd(); + } + {//构造方法 + mv = cw.visitMethod(ACC_PUBLIC, "", "()V", null, null); + mv.visitVarInsn(ALOAD, 0); + mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "", "()V", false); + mv.visitInsn(RETURN); + mv.visitMaxs(1, 1); + mv.visitEnd(); + } + cw.visitEnd(); + byte[] bytes = cw.toByteArray(); + Class newClazz = new ClassLoader(loader) { + public final Class loadClass(String name, byte[] b) { + return defineClass(name, b, 0, b.length); + } + }.loadClass(newDynName.replace('/', '.'), bytes); + try { + return newClazz.getField("field").getGenericType(); + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } }