implement basic omni instance construction

This commit is contained in:
金戟 2021-03-17 16:24:20 +08:00
parent 7857782125
commit fe7420c99a
4 changed files with 61 additions and 14 deletions

View File

@ -41,10 +41,9 @@ public class TestableClassTransformer implements ClassFileTransformer {
private static final String CLASS_NAME_MOCK = "Mock"; private static final String CLASS_NAME_MOCK = "Mock";
/** /**
* Just avoid spend time to scan those surely non-user classes Should keep these lists as tiny as possible * Just avoid spend time to scan those surely non-user classes, should keep these lists as tiny as possible
*/ */
private final String[] BLACKLIST_PREFIXES = new String[] {"jdk/", "java/", "javax/", "sun/", "com/sun/", private final String[] BLACKLIST_PREFIXES = new String[] { "sun/", "com/sun/" };
"org/groovy", "org/apache/maven/", "com/alibaba/testable/", "junit/", "org/junit/", "org/testng/"};
public MockClassParser mockClassParser = new MockClassParser(); public MockClassParser mockClassParser = new MockClassParser();

View File

@ -96,7 +96,7 @@ public class OmniAccessor {
} }
private static List<String> generateMemberIndex(String basePath, Class<?> clazz) { private static List<String> generateMemberIndex(String basePath, Class<?> clazz) {
List<Field> fields = getAllFields(clazz); List<Field> fields = TypeUtil.getAllFields(clazz);
List<String> paths = new ArrayList<String>(); List<String> paths = new ArrayList<String>();
for (Field f : fields) { for (Field f : fields) {
if (!f.getName().startsWith(THIS_REF_PREFIX)) { if (!f.getName().startsWith(THIS_REF_PREFIX)) {
@ -108,15 +108,6 @@ public class OmniAccessor {
return paths; return paths;
} }
private static List<Field> getAllFields(Class<?> clazz) {
Class<?> rawClass = clazz.isArray() ? clazz.getComponentType() : clazz;
List<Field> fields = new ArrayList<Field>(Arrays.asList(rawClass.getDeclaredFields()));
if (rawClass.getSuperclass() != null) {
fields.addAll(getAllFields(rawClass.getSuperclass()));
}
return fields;
}
private static String toPath(Field field) { private static String toPath(Field field) {
return field.getName() + BRACE_START + field.getType().getSimpleName() + BRACE_END; return field.getName() + BRACE_START + field.getType().getSimpleName() + BRACE_END;
} }

View File

@ -1,12 +1,19 @@
package com.alibaba.testable.core.tool; package com.alibaba.testable.core.tool;
import com.alibaba.testable.core.model.Null;
import com.alibaba.testable.core.util.TypeUtil;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
/** /**
* @author flin * @author flin
*/ */
public class OmniConstructor { public class OmniConstructor {
public static <T> T newInstance(Class<T> clazz) { public static <T> T newInstance(Class<T> clazz) {
return null; return newInstance(clazz, isJavaAgentEnabled(clazz));
} }
public static <T> void appendInstance(Object target, Class<T> clazz) { public static <T> void appendInstance(Object target, Class<T> clazz) {
@ -17,4 +24,37 @@ public class OmniConstructor {
return; return;
} }
private static boolean isJavaAgentEnabled(Class<?> clazz) {
try {
clazz.getDeclaredConstructor(Null.class);
} catch (NoSuchMethodException e) {
return false;
}
return true;
}
private static <T> T newInstance(Class<T> clazz, boolean withJavaAgent) {
try {
Constructor<?> constructor = withJavaAgent ?
clazz.getDeclaredConstructor(Null.class) : clazz.getDeclaredConstructor();
constructor.setAccessible(true);
Object ins = withJavaAgent ? constructor.newInstance(new Null()) : constructor.newInstance();
for (Field f : TypeUtil.getAllFields(clazz)) {
f.setAccessible(true);
if (!f.getType().isPrimitive()) {
f.set(ins, newInstance(f.getType(), withJavaAgent));
}
}
return (T)ins;
} catch (NoSuchMethodException e) {
return null;
} catch (IllegalAccessException e) {
return null;
} catch (InstantiationException e) {
return null;
} catch (InvocationTargetException e) {
return null;
}
}
} }

View File

@ -3,6 +3,9 @@ package com.alibaba.testable.core.util;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/** /**
* @author flin * @author flin
@ -41,6 +44,20 @@ public class TypeUtil {
} }
} }
/**
* get all field from class and its parents
* @param clazz class contains fields
* @return all fields available
*/
public static List<Field> getAllFields(Class<?> clazz) {
Class<?> rawClass = clazz.isArray() ? clazz.getComponentType() : clazz;
List<Field> fields = new ArrayList<Field>(Arrays.asList(rawClass.getDeclaredFields()));
if (rawClass.getSuperclass() != null) {
fields.addAll(getAllFields(rawClass.getSuperclass()));
}
return fields;
}
/** /**
* get constructor by parameter matching * get constructor by parameter matching
* @param clazz class to construct * @param clazz class to construct