Creator增加paramTypes方法

This commit is contained in:
redkale
2023-01-29 17:37:28 +08:00
parent 83b4887dd6
commit 0b5a8863f3
2 changed files with 188 additions and 46 deletions

View File

@@ -7,17 +7,16 @@ package org.redkale.util;
import java.io.*; import java.io.*;
import java.lang.reflect.*; import java.lang.reflect.*;
import java.net.*; import java.net.*;
import java.util.*;
import java.util.AbstractMap.SimpleEntry; import java.util.AbstractMap.SimpleEntry;
import java.util.*;
import java.util.concurrent.*; import java.util.concurrent.*;
import java.util.function.*; import java.util.function.*;
import java.util.logging.*; import java.util.logging.*;
import java.util.stream.Stream; import java.util.stream.Stream;
import org.redkale.annotation.ConstructorParameters; import org.redkale.annotation.ConstructorParameters;
import org.redkale.asm.*; import org.redkale.asm.*;
import org.redkale.asm.Type;
import static org.redkale.asm.Opcodes.*; import static org.redkale.asm.Opcodes.*;
import org.redkale.asm.Type;
/** /**
* <p> * <p>
@@ -97,6 +96,11 @@ public interface Creator<T> {
public Map.Entry create(Object... params) { public Map.Entry create(Object... params) {
return new AbstractMap.SimpleEntry(params[0], params[1]); return new AbstractMap.SimpleEntry(params[0], params[1]);
} }
@Override
public Class[] paramTypes() {
return new Class[]{Object.class, Object.class};
}
}); });
creatorCacheMap.put(AbstractMap.SimpleEntry.class, new Creator<AbstractMap.SimpleEntry>() { creatorCacheMap.put(AbstractMap.SimpleEntry.class, new Creator<AbstractMap.SimpleEntry>() {
@Override @Override
@@ -104,6 +108,11 @@ public interface Creator<T> {
public AbstractMap.SimpleEntry create(Object... params) { public AbstractMap.SimpleEntry create(Object... params) {
return new AbstractMap.SimpleEntry(params[0], params[1]); return new AbstractMap.SimpleEntry(params[0], params[1]);
} }
@Override
public Class[] paramTypes() {
return new Class[]{Object.class, Object.class};
}
}); });
creatorCacheMap.put(AnyValue.DefaultAnyValue.class, p -> new AnyValue.DefaultAnyValue()); creatorCacheMap.put(AnyValue.DefaultAnyValue.class, p -> new AnyValue.DefaultAnyValue());
creatorCacheMap.put(AnyValue.class, p -> new AnyValue.DefaultAnyValue()); creatorCacheMap.put(AnyValue.class, p -> new AnyValue.DefaultAnyValue());
@@ -136,15 +145,23 @@ public interface Creator<T> {
@Override @Override
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
if (java.lang.reflect.Modifier.isStatic(access) || !"<init>".equals(name)) return null; if (java.lang.reflect.Modifier.isStatic(access) || !"<init>".equals(name)) {
if (constructorDesc != null && !constructorDesc.equals(desc)) return null; return null;
if (this.started) return null; }
if (constructorDesc != null && !constructorDesc.equals(desc)) {
return null;
}
if (this.started) {
return null;
}
this.started = true; this.started = true;
//返回的List中参数列表可能会比方法参数量多因为方法内的临时变量也会存入list中 所以需要list的元素集合比方法的参数多 //返回的List中参数列表可能会比方法参数量多因为方法内的临时变量也会存入list中 所以需要list的元素集合比方法的参数多
return new MethodVisitor(Opcodes.ASM6) { return new MethodVisitor(Opcodes.ASM6) {
@Override @Override
public void visitLocalVariable(String name, String description, String signature, Label start, Label end, int index) { public void visitLocalVariable(String name, String description, String signature, Label start, Label end, int index) {
if (index < 1) return; if (index < 1) {
return;
}
int size = fieldnames.size(); int size = fieldnames.size();
//index不会按顺序执行的 //index不会按顺序执行的
if (index > size) { if (index > size) {
@@ -162,7 +179,9 @@ public interface Creator<T> {
public static SimpleEntry<String, Class>[] getConstructorField(Class clazz, int paramcount, String constructorDesc) { public static SimpleEntry<String, Class>[] getConstructorField(Class clazz, int paramcount, String constructorDesc) {
String n = clazz.getName(); String n = clazz.getName();
InputStream in = clazz.getResourceAsStream(n.substring(n.lastIndexOf('.') + 1) + ".class"); InputStream in = clazz.getResourceAsStream(n.substring(n.lastIndexOf('.') + 1) + ".class");
if (in == null) return null; if (in == null) {
return null;
}
ByteArrayOutputStream out = new ByteArrayOutputStream(1024); ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
byte[] bytes = new byte[1024]; byte[] bytes = new byte[1024];
int pos; int pos;
@@ -177,7 +196,9 @@ public interface Creator<T> {
final List<String> fieldnames = new ArrayList<>(); final List<String> fieldnames = new ArrayList<>();
new ClassReader(out.toByteArray()).accept(new SimpleClassVisitor(Opcodes.ASM6, fieldnames, constructorDesc), 0); new ClassReader(out.toByteArray()).accept(new SimpleClassVisitor(Opcodes.ASM6, fieldnames, constructorDesc), 0);
while (fieldnames.remove(" ")); //删掉空元素 while (fieldnames.remove(" ")); //删掉空元素
if (fieldnames.isEmpty()) return null; if (fieldnames.isEmpty()) {
return null;
}
if (paramcount == fieldnames.size()) { if (paramcount == fieldnames.size()) {
return getConstructorField(clazz, paramcount, fieldnames.toArray(new String[fieldnames.size()])); return getConstructorField(clazz, paramcount, fieldnames.toArray(new String[fieldnames.size()]));
} else { } else {
@@ -205,10 +226,14 @@ public interface Creator<T> {
} catch (NoSuchFieldException nsfe) { } catch (NoSuchFieldException nsfe) {
} }
} }
if (field == null) return null; if (field == null) {
return null;
}
se[i] = new SimpleEntry<>(field.getName(), field.getType()); se[i] = new SimpleEntry<>(field.getName(), field.getType());
} catch (Exception e) { } catch (Exception e) {
if (logger.isLoggable(Level.FINE)) logger.log(Level.FINE, clazz + " getConstructorField error", e); if (logger.isLoggable(Level.FINE)) {
logger.log(Level.FINE, clazz + " getConstructorField error", e);
}
return null; return null;
} }
} }
@@ -296,9 +321,9 @@ public interface Creator<T> {
RedkaleClassLoader.putReflectionDeclaredConstructors(resultClazz, newDynName.replace('/', '.')); RedkaleClassLoader.putReflectionDeclaredConstructors(resultClazz, newDynName.replace('/', '.'));
return (IntFunction<T[]>) resultClazz.getDeclaredConstructor().newInstance(); return (IntFunction<T[]>) resultClazz.getDeclaredConstructor().newInstance();
} catch (Exception ex) { } catch (Exception ex) {
ex.printStackTrace(); //一般不会发生 //ex.printStackTrace(); //一般不会发生
return t -> (T[]) Array.newInstance(clazz, t); //return t -> (T[]) Array.newInstance(clazz, t);
//throw new RuntimeException(ex); throw new RuntimeException(ex);
} }
} }
} }
@@ -312,6 +337,15 @@ public interface Creator<T> {
*/ */
public T create(Object... params); public T create(Object... params);
/**
* 参数类型数组
*
* @return 参数类型数组
*/
default Class[] paramTypes() {
return new Class[0];
}
/** /**
* 创建指定类型对象数组的IntFunction * 创建指定类型对象数组的IntFunction
* *
@@ -334,16 +368,36 @@ public interface Creator<T> {
* @return 数组 * @return 数组
*/ */
public static <T> T[] newArray(final Class<T> type, final int size) { public static <T> T[] newArray(final Class<T> type, final int size) {
if (type == int.class) return (T[]) (Object) new int[size]; if (type == int.class) {
if (type == byte.class) return (T[]) (Object) new byte[size]; return (T[]) (Object) new int[size];
if (type == long.class) return (T[]) (Object) new long[size]; }
if (type == String.class) return (T[]) new String[size]; if (type == byte.class) {
if (type == Object.class) return (T[]) new Object[size]; return (T[]) (Object) new byte[size];
if (type == boolean.class) return (T[]) (Object) new boolean[size]; }
if (type == short.class) return (T[]) (Object) new short[size]; if (type == long.class) {
if (type == char.class) return (T[]) (Object) new char[size]; return (T[]) (Object) new long[size];
if (type == float.class) return (T[]) (Object) new float[size]; }
if (type == double.class) return (T[]) (Object) new double[size]; if (type == String.class) {
return (T[]) new String[size];
}
if (type == Object.class) {
return (T[]) new Object[size];
}
if (type == boolean.class) {
return (T[]) (Object) new boolean[size];
}
if (type == short.class) {
return (T[]) (Object) new short[size];
}
if (type == char.class) {
return (T[]) (Object) new char[size];
}
if (type == float.class) {
return (T[]) (Object) new float[size];
}
if (type == double.class) {
return (T[]) (Object) new double[size];
}
//return (T[]) Array.newInstance(type, size); //return (T[]) Array.newInstance(type, size);
return arrayFunction(type).apply(size); return arrayFunction(type).apply(size);
} }
@@ -402,14 +456,22 @@ public interface Creator<T> {
clazz = (Class<T>) ArrayList.class; clazz = (Class<T>) ArrayList.class;
} }
Creator creator = CreatorInner.creatorCacheMap.get(clazz); Creator creator = CreatorInner.creatorCacheMap.get(clazz);
if (creator != null) return creator; if (creator != null) {
return creator;
}
if (clazz.isInterface() || Modifier.isAbstract(clazz.getModifiers())) { if (clazz.isInterface() || Modifier.isAbstract(clazz.getModifiers())) {
throw new RuntimeException("[" + clazz + "] is a interface or abstract class, cannot create it's Creator."); throw new RuntimeException("[" + clazz + "] is a interface or abstract class, cannot create it's Creator.");
} }
for (final Method method : clazz.getDeclaredMethods()) { //查找类中是否存在提供创建Creator实例的静态方法 for (final Method method : clazz.getDeclaredMethods()) { //查找类中是否存在提供创建Creator实例的静态方法
if (!Modifier.isStatic(method.getModifiers())) continue; if (!Modifier.isStatic(method.getModifiers())) {
if (method.getParameterTypes().length != 0) continue; continue;
if (method.getReturnType() != Creator.class) continue; }
if (method.getParameterTypes().length != 0) {
continue;
}
if (method.getReturnType() != Creator.class) {
continue;
}
try { try {
method.setAccessible(true); method.setAccessible(true);
Creator<T> c = (Creator) method.invoke(null); Creator<T> c = (Creator) method.invoke(null);
@@ -451,7 +513,9 @@ public interface Creator<T> {
if (constructor0 == null) { // 2、查找public带ConstructorParameters注解的构造函数 if (constructor0 == null) { // 2、查找public带ConstructorParameters注解的构造函数
for (Constructor c : clazz.getConstructors()) { for (Constructor c : clazz.getConstructors()) {
ConstructorParameters cp = (ConstructorParameters) c.getAnnotation(ConstructorParameters.class); ConstructorParameters cp = (ConstructorParameters) c.getAnnotation(ConstructorParameters.class);
if (cp == null) continue; if (cp == null) {
continue;
}
SimpleEntry<String, Class>[] fields = CreatorInner.getConstructorField(clazz, c.getParameterCount(), cp.value()); SimpleEntry<String, Class>[] fields = CreatorInner.getConstructorField(clazz, c.getParameterCount(), cp.value());
if (fields != null) { if (fields != null) {
constructor0 = c; constructor0 = c;
@@ -463,8 +527,12 @@ public interface Creator<T> {
if (constructor0 == null) { // 3、查找public且不带ConstructorParameters注解的构造函数 if (constructor0 == null) { // 3、查找public且不带ConstructorParameters注解的构造函数
List<Constructor> cs = new ArrayList<>(); List<Constructor> cs = new ArrayList<>();
for (Constructor c : clazz.getConstructors()) { for (Constructor c : clazz.getConstructors()) {
if (c.getAnnotation(ConstructorParameters.class) != null) continue; if (c.getAnnotation(ConstructorParameters.class) != null) {
if (c.getParameterCount() < 1) continue; continue;
}
if (c.getParameterCount() < 1) {
continue;
}
cs.add(c); cs.add(c);
} }
//优先参数最多的构造函数 //优先参数最多的构造函数
@@ -480,9 +548,13 @@ public interface Creator<T> {
} }
if (constructor0 == null) { // 4、查找非private带ConstructorParameters的构造函数 if (constructor0 == null) { // 4、查找非private带ConstructorParameters的构造函数
for (Constructor c : clazz.getDeclaredConstructors()) { for (Constructor c : clazz.getDeclaredConstructors()) {
if (Modifier.isPublic(c.getModifiers()) || Modifier.isPrivate(c.getModifiers())) continue; if (Modifier.isPublic(c.getModifiers()) || Modifier.isPrivate(c.getModifiers())) {
continue;
}
ConstructorParameters cp = (ConstructorParameters) c.getAnnotation(ConstructorParameters.class); ConstructorParameters cp = (ConstructorParameters) c.getAnnotation(ConstructorParameters.class);
if (cp == null) continue; if (cp == null) {
continue;
}
SimpleEntry<String, Class>[] fields = CreatorInner.getConstructorField(clazz, c.getParameterCount(), cp.value()); SimpleEntry<String, Class>[] fields = CreatorInner.getConstructorField(clazz, c.getParameterCount(), cp.value());
if (fields != null) { if (fields != null) {
constructor0 = c; constructor0 = c;
@@ -494,9 +566,15 @@ public interface Creator<T> {
if (constructor0 == null) { // 5、查找非private且不带ConstructorParameters的构造函数 if (constructor0 == null) { // 5、查找非private且不带ConstructorParameters的构造函数
List<Constructor> cs = new ArrayList<>(); List<Constructor> cs = new ArrayList<>();
for (Constructor c : clazz.getDeclaredConstructors()) { for (Constructor c : clazz.getDeclaredConstructors()) {
if (Modifier.isPublic(c.getModifiers()) || Modifier.isPrivate(c.getModifiers())) continue; if (Modifier.isPublic(c.getModifiers()) || Modifier.isPrivate(c.getModifiers())) {
if (c.getAnnotation(ConstructorParameters.class) != null) continue; continue;
if (c.getParameterCount() < 1) continue; }
if (c.getAnnotation(ConstructorParameters.class) != null) {
continue;
}
if (c.getParameterCount() < 1) {
continue;
}
cs.add(c); cs.add(c);
} }
//优先参数最多的构造函数 //优先参数最多的构造函数
@@ -515,6 +593,7 @@ public interface Creator<T> {
if (constructor == null || constructorParameters == null) { if (constructor == null || constructorParameters == null) {
throw new RuntimeException("[" + clazz + "] have no public or ConstructorParameters-Annotation constructor."); throw new RuntimeException("[" + clazz + "] have no public or ConstructorParameters-Annotation constructor.");
} }
final int[] iconsts = {ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4, ICONST_5};
//------------------------------------------------------------- //-------------------------------------------------------------
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
FieldVisitor fv; FieldVisitor fv;
@@ -530,6 +609,57 @@ public interface Creator<T> {
mv.visitMaxs(1, 1); mv.visitMaxs(1, 1);
mv.visitEnd(); mv.visitEnd();
} }
{//paramTypes 方法
mv = cw.visitMethod(ACC_PUBLIC, "paramTypes", "()[Ljava/lang/Class;", null, null);
int paramLen = constructorParameters.length;
if (paramLen < 6) {
mv.visitInsn(ICONST_0 + paramLen);
} else if (paramLen <= Byte.MAX_VALUE) {
mv.visitIntInsn(BIPUSH, paramLen);
} else if (paramLen <= Short.MAX_VALUE) {
mv.visitIntInsn(SIPUSH, paramLen);
} else {
mv.visitLdcInsn(paramLen);
}
mv.visitTypeInsn(ANEWARRAY, "java/lang/Class");
for (int i = 0; i < constructorParameters.length; i++) {
final Class pt = constructorParameters[i].getValue();
mv.visitInsn(DUP);
if (i < 6) {
mv.visitInsn(iconsts[i]);
} else if (i <= Byte.MAX_VALUE) {
mv.visitIntInsn(BIPUSH, i);
} else if (i <= Short.MAX_VALUE) {
mv.visitIntInsn(SIPUSH, i);
} else {
mv.visitLdcInsn(i);
}
if (pt == boolean.class) {
mv.visitFieldInsn(GETSTATIC, "java/lang/Boolean", "TYPE", "Ljava/lang/Class;");
} else if (pt == byte.class) {
mv.visitFieldInsn(GETSTATIC, "java/lang/Byte", "TYPE", "Ljava/lang/Class;");
} else if (pt == char.class) {
mv.visitFieldInsn(GETSTATIC, "java/lang/Character", "TYPE", "Ljava/lang/Class;");
} else if (pt == short.class) {
mv.visitFieldInsn(GETSTATIC, "java/lang/Short", "TYPE", "Ljava/lang/Class;");
} else if (pt == int.class) {
mv.visitFieldInsn(GETSTATIC, "java/lang/Integer", "TYPE", "Ljava/lang/Class;");
} else if (pt == float.class) {
mv.visitFieldInsn(GETSTATIC, "java/lang/Float", "TYPE", "Ljava/lang/Class;");
} else if (pt == long.class) {
mv.visitFieldInsn(GETSTATIC, "java/lang/Long", "TYPE", "Ljava/lang/Class;");
} else if (pt == double.class) {
mv.visitFieldInsn(GETSTATIC, "java/lang/Double", "TYPE", "Ljava/lang/Class;");
} else {
mv.visitLdcInsn(Type.getType(Type.getDescriptor(pt)));
}
mv.visitInsn(AASTORE);
}
mv.visitInsn(ARETURN);
mv.visitMaxs(4, 1);
mv.visitEnd();
}
{//create 方法 {//create 方法
mv = cw.visitMethod(ACC_PUBLIC + ACC_VARARGS, "create", "([Ljava/lang/Object;)L" + interName + ";", null, null); mv = cw.visitMethod(ACC_PUBLIC + ACC_VARARGS, "create", "([Ljava/lang/Object;)L" + interName + ";", null, null);
if (constructorParameters.length > 0) { if (constructorParameters.length > 0) {
@@ -541,11 +671,12 @@ public interface Creator<T> {
av1.visitEnd(); av1.visitEnd();
av0.visitEnd(); av0.visitEnd();
} }
final int[] iconsts = {ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4, ICONST_5};
{ //有Primitive数据类型且值为null的参数需要赋默认值 { //有Primitive数据类型且值为null的参数需要赋默认值
for (int i = 0; i < constructorParameters.length; i++) { for (int i = 0; i < constructorParameters.length; i++) {
final Class pt = constructorParameters[i].getValue(); final Class pt = constructorParameters[i].getValue();
if (!pt.isPrimitive()) continue; if (!pt.isPrimitive()) {
continue;
}
mv.visitVarInsn(ALOAD, 1); mv.visitVarInsn(ALOAD, 1);
if (i < 6) { if (i < 6) {
mv.visitInsn(iconsts[i]); mv.visitInsn(iconsts[i]);
@@ -673,13 +804,17 @@ public interface Creator<T> {
t.printStackTrace(); t.printStackTrace();
} }
} }
if (!ispub && resultClazz == null) throw new RuntimeException("[" + clazz + "] have no public or ConstructorParameters-Annotation constructor."); if (!ispub && resultClazz == null) {
throw new RuntimeException("[" + clazz + "] have no public or ConstructorParameters-Annotation constructor.");
}
try { try {
if (resultClazz == null) resultClazz = new ClassLoader(loader) { if (resultClazz == null) {
resultClazz = new ClassLoader(loader) {
public final Class<?> loadClass(String name, byte[] b) { public final Class<?> loadClass(String name, byte[] b) {
return defineClass(name, b, 0, b.length); return defineClass(name, b, 0, b.length);
} }
}.loadClass(newDynName.replace('/', '.'), bytes); }.loadClass(newDynName.replace('/', '.'), bytes);
}
RedkaleClassLoader.putDynClass(newDynName.replace('/', '.'), bytes, resultClazz); RedkaleClassLoader.putDynClass(newDynName.replace('/', '.'), bytes, resultClazz);
RedkaleClassLoader.putReflectionDeclaredConstructors(resultClazz, newDynName.replace('/', '.')); RedkaleClassLoader.putReflectionDeclaredConstructors(resultClazz, newDynName.replace('/', '.'));
return (Creator) resultClazz.getDeclaredConstructor().newInstance(); return (Creator) resultClazz.getDeclaredConstructor().newInstance();

View File

@@ -5,9 +5,11 @@
*/ */
package org.redkale.test.util; package org.redkale.test.util;
import java.util.Arrays;
import org.junit.jupiter.api.*;
import org.redkale.annotation.ConstructorParameters; import org.redkale.annotation.ConstructorParameters;
import org.redkale.convert.json.*; import org.redkale.convert.json.JsonConvert;
import org.redkale.util.*; import org.redkale.util.Creator;
/** /**
* *
@@ -34,7 +36,7 @@ public class CreatorRecord {
private double dval; private double dval;
@ConstructorParameters({"id", "name", "lval", "tval", "bval", "sval", "cval", "fval", "dval"}) @ConstructorParameters({"id", "name", "lval", "tval", "bval", "sval", "cval", "fval", "dval"})
CreatorRecord(int id, String name, long lval, boolean tval, byte bval, short sval, char cval, float fval, double dval) { public CreatorRecord(int id, String name, long lval, boolean tval, byte bval, short sval, char cval, float fval, double dval) {
this.id = id; this.id = id;
this.name = name; this.name = name;
this.lval = lval; this.lval = lval;
@@ -46,11 +48,16 @@ public class CreatorRecord {
this.dval = dval; this.dval = dval;
} }
public static void main(String[] args) throws Exception { @Test
CreatorRecord record = Creator.create(CreatorRecord.class).create(new Object[]{null, "ss", null, true, null, (short) 45, null, 4.3f, null}); public void run1() {
Creator<CreatorRecord> creator = Creator.create(CreatorRecord.class);
System.out.println(Arrays.toString(creator.paramTypes()));
CreatorRecord record = creator.create(new Object[]{null, "ss", null, true, null, (short) 45, null, 4.3f, null});
String json = record.toString(); String json = record.toString();
System.out.println(json); System.out.println(json);
System.out.println(JsonConvert.root().convertFrom(CreatorRecord.class, json).toString()); String json2 = JsonConvert.root().convertFrom(CreatorRecord.class, json).toString();
System.out.println(json2);
Assertions.assertEquals(json, json2);
} }
@Override @Override