Creator优化

This commit is contained in:
redkale
2023-08-12 14:05:27 +08:00
parent a6de4df777
commit e729f04917
7 changed files with 302 additions and 27 deletions

View File

@@ -59,7 +59,7 @@ public class ArrayDecoder<T> implements Decodeable<Reader, T[]> {
}
factory.register(type, this);
this.componentDecoder = factory.loadDecoder(this.componentType);
this.componentArrayFunction = Creator.arrayFunction(this.componentClass);
this.componentArrayFunction = Creator.funcArray(this.componentClass);
} finally {
inited = true;
lock.lock();

View File

@@ -365,7 +365,7 @@ public final class EntityInfo<T> {
}
this.tableStrategy = dts;
this.arrayer = Creator.arrayFunction(type);
this.arrayer = Creator.funcArray(type);
Creator creator = Creator.create(type);
String[] cps = null;
try {

View File

@@ -104,7 +104,7 @@ public interface Copier<S, D> extends BiFunction<S, D, D> {
*/
public static <S, D> D copy(final S src, final D dest, final int options) {
if (src == null || dest == null) {
return null;
return dest;
}
return load((Class<S>) src.getClass(), (Class<D>) dest.getClass(), options).apply(src, dest);
}
@@ -174,6 +174,52 @@ public interface Copier<S, D> extends BiFunction<S, D, D> {
return func(srcClass, destClass, 0);
}
/**
* 创建源类到目标类的复制器并缓存
*
* @param <D> 目标类泛型
* @param <S> 源类泛型
* @param destClass 目标类名
* @param srcClass 源类名
* @param options 可配项
*
* @return 复制器
*/
public static <S, D> Function<Collection<S>, Set<D>> funcSet(final Class<S> srcClass, final Class<D> destClass) {
return funcSet(srcClass, destClass, 0);
}
/**
* 创建源类到目标类的复制器并缓存
*
* @param <D> 目标类泛型
* @param <S> 源类泛型
* @param destClass 目标类名
* @param srcClass 源类名
* @param options 可配项
*
* @return 复制器
*/
public static <S, D> Function<Collection<S>, List<D>> funcList(final Class<S> srcClass, final Class<D> destClass) {
return funcList(srcClass, destClass, 0);
}
/**
* 创建源类到目标类的复制器并缓存
*
* @param <D> 目标类泛型
* @param <S> 源类泛型
* @param destClass 目标类名
* @param srcClass 源类名
* @param collectionClass 集合类名
*
* @return 复制器
*/
public static <S, D, C extends Collection> Function<Collection<S>, Collection<D>> funcCollection(final Class<S> srcClass,
final Class<D> destClass, final Class<C> collectionClass) {
return funcCollection(srcClass, destClass, 0, collectionClass);
}
/**
* 创建源类到目标类的复制器并缓存
*
@@ -188,6 +234,98 @@ public interface Copier<S, D> extends BiFunction<S, D, D> {
return load(srcClass, destClass, 0);
}
/**
* 创建源类到目标类的复制器并缓存
*
* @param <D> 目标类泛型
* @param <S> 源类泛型
* @param destClass 目标类名
* @param srcClass 源类名
* @param options 可配项
*
* @return 复制器
*/
public static <S, D> Function<Collection<S>, Set<D>> funcSet(final Class<S> srcClass, final Class<D> destClass, final int options) {
return (Function) funcCollection(srcClass, destClass, options, LinkedHashSet.class);
}
/**
* 创建源类到目标类的复制器并缓存
*
* @param <D> 目标类泛型
* @param <S> 源类泛型
* @param destClass 目标类名
* @param srcClass 源类名
* @param options 可配项
*
* @return 复制器
*/
public static <S, D> Function<Collection<S>, List<D>> funcList(final Class<S> srcClass, final Class<D> destClass, final int options) {
return (Function) funcCollection(srcClass, destClass, options, ArrayList.class);
}
/**
* 创建源类到目标类的复制器并缓存
*
* @param <D> 目标类泛型
* @param <S> 源类泛型
* @param destClass 目标类名
* @param srcClass 源类名
* @param options 可配项
* @param collectionClass 集合类名
*
* @return 复制器
*/
public static <S, D, C extends Collection> Function<Collection<S>, Collection<D>> funcCollection(final Class<S> srcClass, final Class<D> destClass,
final int options, final Class<C> collectionClass) {
if (destClass == srcClass) {
return CopierInner.funcListOneCaches
.computeIfAbsent(collectionClass, t -> new ConcurrentHashMap<>())
.computeIfAbsent(options, t -> new ConcurrentHashMap<>())
.computeIfAbsent(srcClass, v -> {
Creator<C> creator = Creator.create(collectionClass);
Function<S, D> func = func(srcClass, destClass, options);
Function<Collection<S>, Collection<D>> funcList = srcs -> {
if (srcs == null) {
return null;
} else if (srcs.isEmpty()) {
return creator.create();
} else {
C list = creator.create();
for (S s : srcs) {
list.add(func.apply(s));
}
return list;
}
};
return funcList;
});
} else {
return CopierInner.funcListTwoCaches
.computeIfAbsent(collectionClass, t -> new ConcurrentHashMap<>())
.computeIfAbsent(options, t -> new ConcurrentHashMap<>())
.computeIfAbsent(srcClass, t -> new ConcurrentHashMap<>())
.computeIfAbsent(destClass, v -> {
Creator<C> creator = Creator.create(collectionClass);
Function<S, D> func = func(srcClass, destClass, options);
Function<Collection<S>, Collection<D>> funcList = srcs -> {
if (srcs == null) {
return null;
} else if (srcs.isEmpty()) {
return (C) creator.create();
} else {
C list = creator.create();
for (S s : srcs) {
list.add(func.apply(s));
}
return list;
}
};
return funcList;
});
}
}
/**
* 创建源类到目标类的复制器并缓存
*
@@ -388,7 +526,7 @@ public interface Copier<S, D> extends BiFunction<S, D, D> {
if (nameAlias != null) {
return (S src, D dest) -> {
if (src == null) {
return null;
return dest;
}
Map d = (Map) dest;
((Map) src).forEach((k, v) -> {
@@ -401,7 +539,7 @@ public interface Copier<S, D> extends BiFunction<S, D, D> {
} else {
return (S src, D dest) -> {
if (src == null) {
return null;
return dest;
}
Map d = (Map) dest;
((Map) src).forEach((k, v) -> {
@@ -415,7 +553,7 @@ public interface Copier<S, D> extends BiFunction<S, D, D> {
} else if (nameAlias != null) {
return (S src, D dest) -> {
if (src == null) {
return null;
return dest;
}
Map d = (Map) dest;
((Map) src).forEach((k, v) -> {
@@ -430,7 +568,7 @@ public interface Copier<S, D> extends BiFunction<S, D, D> {
@Override
public D apply(S src, D dest) {
if (src == null) {
return null;
return dest;
}
if (options == 0) {
((Map) dest).putAll((Map) src);
@@ -1013,6 +1151,18 @@ public interface Copier<S, D> extends BiFunction<S, D, D> {
static final ConcurrentHashMap<Integer, ConcurrentHashMap<Class, ConcurrentHashMap<Class, Function>>> funcTwoCaches = new ConcurrentHashMap();
static final ConcurrentHashMap<Class, ConcurrentHashMap<Integer, ConcurrentHashMap<Class, Function>>> funcListOneCaches = new ConcurrentHashMap();
static final ConcurrentHashMap<Class, ConcurrentHashMap<Integer, ConcurrentHashMap<Class, ConcurrentHashMap<Class, Function>>>> funcListTwoCaches = new ConcurrentHashMap();
public static void clear() {
copierOneCaches.clear();
copierTwoCaches.clear();
funcOneCaches.clear();
funcTwoCaches.clear();
funcListOneCaches.clear();
funcListTwoCaches.clear();
}
}
}

View File

@@ -6,6 +6,7 @@ package org.redkale.util;
import java.io.*;
import java.lang.reflect.*;
import java.math.*;
import java.net.*;
import java.nio.ByteBuffer;
import java.util.AbstractMap.SimpleEntry;
@@ -100,10 +101,26 @@ public interface Creator<T> {
*
* @return IntFunction
*/
public static <T> IntFunction<T[]> arrayFunction(final Class<T> type) {
public static <T> IntFunction<T[]> funcArray(final Class<T> type) {
return CreatorInner.arrayCacheMap.computeIfAbsent(type, CreatorInner::createArrayFunction);
}
public static <T> Creator<T> load(Class<T> clazz) {
return CreatorInner.creatorCacheMap.computeIfAbsent(clazz, v -> create(clazz));
}
public static <T> Creator<T> register(Class<T> clazz, final Supplier<T> supplier) {
Creator<T> creator = (Object... params) -> supplier.get();
CreatorInner.creatorCacheMap.put(clazz, creator);
return creator;
}
public static <T> Creator<T> register(final LambdaSupplier<T> supplier) {
Creator<T> creator = (Object... params) -> supplier.get();
CreatorInner.creatorCacheMap.put(LambdaSupplier.readClass(supplier), creator);
return creator;
}
/**
* 创建指定大小的对象数组
*
@@ -144,7 +161,7 @@ public interface Creator<T> {
if (type == double.class) {
return (T[]) (Object) new double[size];
}
return arrayFunction(type).apply(size);
return funcArray(type).apply(size);
}
/**
@@ -173,10 +190,6 @@ public interface Creator<T> {
return (Object... params) -> func.apply(params);
}
public static <T> Creator<T> load(Class<T> clazz) {
return CreatorInner.creatorCacheMap.computeIfAbsent(clazz, v -> create(clazz));
}
/**
* 根据指定的class采用ASM技术生产Creator。
*
@@ -187,19 +200,29 @@ public interface Creator<T> {
*/
@SuppressWarnings("unchecked")
public static <T> Creator<T> create(Class<T> clazz) {
if (List.class.isAssignableFrom(clazz) && (clazz.isAssignableFrom(ArrayList.class) || clazz.getName().startsWith("java.util.Collections") || clazz.getName().startsWith("java.util.ImmutableCollections") || clazz.getName().startsWith("java.util.Arrays"))) {
if (List.class.isAssignableFrom(clazz) && (clazz.isAssignableFrom(ArrayList.class)
|| clazz.getName().startsWith("java.util.Collections")
|| clazz.getName().startsWith("java.util.ImmutableCollections")
|| clazz.getName().startsWith("java.util.Arrays"))) {
clazz = (Class<T>) ArrayList.class;
} else if (Map.class.isAssignableFrom(clazz) && (clazz.isAssignableFrom(HashMap.class) || clazz.getName().startsWith("java.util.Collections") || clazz.getName().startsWith("java.util.ImmutableCollections"))) {
} else if (Map.class.isAssignableFrom(clazz) && (clazz.isAssignableFrom(HashMap.class)
|| clazz.getName().startsWith("java.util.Collections")
|| clazz.getName().startsWith("java.util.ImmutableCollections"))) {
clazz = (Class<T>) HashMap.class;
} else if (Set.class.isAssignableFrom(clazz) && (clazz.isAssignableFrom(HashSet.class) || clazz.getName().startsWith("java.util.Collections") || clazz.getName().startsWith("java.util.ImmutableCollections"))) {
} else if (Set.class.isAssignableFrom(clazz) && (clazz.isAssignableFrom(HashSet.class)
|| clazz.getName().startsWith("java.util.Collections")
|| clazz.getName().startsWith("java.util.ImmutableCollections"))) {
clazz = (Class<T>) HashSet.class;
} else if (Map.class.isAssignableFrom(clazz) && clazz.isAssignableFrom(ConcurrentHashMap.class)) {
clazz = (Class<T>) ConcurrentHashMap.class;
} else if (Deque.class.isAssignableFrom(clazz) && (clazz.isAssignableFrom(ArrayDeque.class) || clazz.getName().startsWith("java.util.Collections") || clazz.getName().startsWith("java.util.ImmutableCollections"))) {
} else if (Deque.class.isAssignableFrom(clazz) && (clazz.isAssignableFrom(ArrayDeque.class)
|| clazz.getName().startsWith("java.util.Collections")
|| clazz.getName().startsWith("java.util.ImmutableCollections"))) {
clazz = (Class<T>) ArrayDeque.class;
} else if (Collection.class.isAssignableFrom(clazz) && clazz.isAssignableFrom(ArrayList.class)) {
clazz = (Class<T>) ArrayList.class;
} else if (Map.Entry.class.isAssignableFrom(clazz) && (Modifier.isInterface(clazz.getModifiers()) || Modifier.isAbstract(clazz.getModifiers()) || !Modifier.isPublic(clazz.getModifiers()))) {
} else if (Map.Entry.class.isAssignableFrom(clazz)
&& (Modifier.isInterface(clazz.getModifiers()) || Modifier.isAbstract(clazz.getModifiers()) || !Modifier.isPublic(clazz.getModifiers()))) {
clazz = (Class<T>) AbstractMap.SimpleEntry.class;
} else if (Iterable.class == clazz) {
clazz = (Class<T>) ArrayList.class;
@@ -572,11 +595,14 @@ public interface Creator<T> {
creatorCacheMap.put(ArrayList.class, p -> new ArrayList<>());
creatorCacheMap.put(HashMap.class, p -> new HashMap<>());
creatorCacheMap.put(HashSet.class, p -> new HashSet<>());
creatorCacheMap.put(LinkedHashSet.class, p -> new LinkedHashSet<>());
creatorCacheMap.put(Stream.class, p -> new ArrayList<>().stream());
creatorCacheMap.put(ConcurrentHashMap.class, p -> new ConcurrentHashMap<>());
creatorCacheMap.put(CompletableFuture.class, p -> new CompletableFuture<>());
creatorCacheMap.put(CompletionStage.class, p -> new CompletableFuture<>());
creatorCacheMap.put(Future.class, p -> new CompletableFuture<>());
creatorCacheMap.put(AnyValue.DefaultAnyValue.class, p -> new AnyValue.DefaultAnyValue());
creatorCacheMap.put(AnyValue.class, p -> new AnyValue.DefaultAnyValue());
creatorCacheMap.put(Map.Entry.class, new Creator<Map.Entry>() {
@Override
@ConstructorParameters({"key", "value"})
@@ -601,8 +627,6 @@ public interface Creator<T> {
return new Class[]{Object.class, Object.class};
}
});
creatorCacheMap.put(AnyValue.DefaultAnyValue.class, p -> new AnyValue.DefaultAnyValue());
creatorCacheMap.put(AnyValue.class, p -> new AnyValue.DefaultAnyValue());
arrayCacheMap.put(int.class, t -> new int[t]);
arrayCacheMap.put(byte.class, t -> new byte[t]);
@@ -614,6 +638,8 @@ public interface Creator<T> {
arrayCacheMap.put(char.class, t -> new char[t]);
arrayCacheMap.put(float.class, t -> new float[t]);
arrayCacheMap.put(double.class, t -> new double[t]);
arrayCacheMap.put(BigInteger.class, t -> new BigInteger[t]);
arrayCacheMap.put(BigDecimal.class, t -> new BigDecimal[t]);
arrayCacheMap.put(ByteBuffer.class, t -> new ByteBuffer[t]);
arrayCacheMap.put(SocketAddress.class, t -> new SocketAddress[t]);
arrayCacheMap.put(InetSocketAddress.class, t -> new InetSocketAddress[t]);

View File

@@ -23,4 +23,8 @@ public interface LambdaSupplier<T> extends Supplier<T>, Serializable {
public static <V> String readColumn(LambdaSupplier<V> func) {
return Utility.readFieldName(func);
}
public static <V> Class<V> readClass(LambdaSupplier<V> func) {
return Utility.readClassName(func);
}
}

View File

@@ -51,6 +51,8 @@ public final class Utility {
private static final ConcurrentHashMap<Class, String> lambdaFieldNameCache = new ConcurrentHashMap();
private static final ConcurrentHashMap<Class, Class> lambdaClassNameCache = new ConcurrentHashMap();
private static final Class JAVA_RECORD_CLASS;
private static final SecureRandom random = new SecureRandom();
@@ -277,6 +279,10 @@ public final class Utility {
return readLambdaFieldName(func);
}
public static Class readClassName(LambdaSupplier func) {
return readLambdaClassName(func);
}
private static String readLambdaFieldName(Serializable func) {
if (!func.getClass().isSynthetic()) { //必须是Lambda表达式的合成类
throw new RedkaleException("Not a synthetic lambda class");
@@ -310,6 +316,43 @@ public final class Utility {
}
}
private static Class readLambdaClassName(Serializable func) {
if (!func.getClass().isSynthetic()) { //必须是Lambda表达式的合成类
throw new RedkaleException("Not a synthetic lambda class");
}
return lambdaClassNameCache.computeIfAbsent(func.getClass(), clazz -> {
try {
MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(func.getClass(), MethodHandles.lookup());
MethodHandle mh = lookup.findVirtual(func.getClass(), "writeReplace", MethodType.methodType(Object.class));
String methodName = ((java.lang.invoke.SerializedLambda) mh.invoke(func)).getImplMethodName();
String className = methodName.contains("lambda$") ? org.redkale.asm.Type.getReturnType(((java.lang.invoke.SerializedLambda) mh.invoke(func)).getInstantiatedMethodType()).getClassName()
: ((java.lang.invoke.SerializedLambda) mh.invoke(func)).getImplClass().replace('/', '.');
return (Class) Thread.currentThread().getContextClassLoader().loadClass(className);
} catch (ClassNotFoundException ex) {
throw new RedkaleException(ex);
} catch (Throwable e) {
return readLambdaClassNameFromBytes(func);
}
});
}
private static Class readLambdaClassNameFromBytes(Serializable func) {
try {
ObjectWriteStream out = new ObjectWriteStream(new ByteArrayOutputStream());
out.writeObject(func);
out.close();
String className = out.classNameReference.get();
if (className != null) {
return (Class) Thread.currentThread().getContextClassLoader().loadClass(className);
} else {
//native-image环境下获取不到methodName
throw new RedkaleException("cannot found method-name from lambda " + func);
}
} catch (Exception e) {
throw new RedkaleException(e);
}
}
static String readFieldName(String methodName) {
String name;
if (methodName.startsWith("is")) {
@@ -332,6 +375,8 @@ public final class Utility {
public final ObjectReference<String> methodNameReference = new ObjectReference<>();
public final ObjectReference<String> classNameReference = new ObjectReference<>();
public ObjectWriteStream(OutputStream out) throws IOException {
super(out);
}
@@ -339,7 +384,11 @@ public final class Utility {
@Override
protected Object replaceObject(Object obj) throws IOException {
if (obj instanceof java.lang.invoke.SerializedLambda) {
methodNameReference.set(((java.lang.invoke.SerializedLambda) obj).getImplMethodName());
String methodName = ((java.lang.invoke.SerializedLambda) obj).getImplMethodName();
methodNameReference.set(methodName);
String className = methodName.contains("lambda$") ? org.redkale.asm.Type.getReturnType(((java.lang.invoke.SerializedLambda) obj).getInstantiatedMethodType()).getClassName()
: ((java.lang.invoke.SerializedLambda) obj).getImplClass().replace('/', '.');
classNameReference.set(className);
}
return super.replaceObject(obj);
}

View File

@@ -5,6 +5,7 @@ package org.redkale.test.util;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;
import org.junit.jupiter.api.*;
import org.redkale.convert.json.JsonConvert;
import org.redkale.util.*;
@@ -36,6 +37,7 @@ public class CopierTest {
test.run17();
test.run18();
test.run19();
test.run20();
}
@Test
@@ -283,12 +285,34 @@ public class CopierTest {
@Test
public void run19() throws Exception {
Bean0 bean1 = new Bean0();
bean1.setCartype(111);
bean1.setCarid(111);
bean1.setUsername("aaa");
Bean0 bean2 = new Bean0();
Copier.load(Bean0.class, Bean0.class, Copier.OPTION_SKIP_NULL_VALUE).apply(bean1, bean2);
System.out.println(JsonConvert.root().convertTo(bean2));
Assertions.assertEquals("aaa", bean2.getUsername());
}
@Test
public void run20() throws Exception {
Bean0 bean1 = new Bean0();
bean1.setCarid(111L);
bean1.setUsername("aaa");
Bean0 bean2 = new Bean0();
bean2.setCarid(111L);
bean2.setUsername("bbb");
Creator.register(Bean0::new);
System.out.println(Copier.load(Bean0.class, Bean0.class).apply(bean1, new Bean0()));
Function<Collection<Bean0>, Set<Bean0>> funcSet = Copier.funcSet(Bean0.class, Bean0.class);
Set<Bean0> set = funcSet.apply(Arrays.asList(bean1, bean2));
Assertions.assertEquals(1, set.size());
Function<Collection<Bean0>, List<Bean0>> funcList = Copier.funcList(Bean0.class, Bean0.class);
List<Bean0> list = funcList.apply(Arrays.asList(bean1, bean2));
Assertions.assertEquals(2, list.size());
System.out.println("------------------------------------------");
}
@@ -347,6 +371,28 @@ public class CopierTest {
this.username = username;
}
@Override
public int hashCode() {
int hash = 5;
hash = 59 * hash + (int) (this.carid ^ (this.carid >>> 32));
return hash;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Bean0 other = (Bean0) obj;
return this.carid == other.carid;
}
@Override
public String toString() {
return JsonConvert.root().convertTo(this);
@@ -354,7 +400,7 @@ public class CopierTest {
}
public class Bean1 {
public static class Bean1 {
public String intval;
@@ -364,7 +410,7 @@ public class CopierTest {
}
}
public class Bean2 {
public static class Bean2 {
public int intval;
@@ -374,7 +420,7 @@ public class CopierTest {
}
}
public class Bean3 {
public static class Bean3 {
private Long seqno;
@@ -392,7 +438,7 @@ public class CopierTest {
}
}
public class Bean4 {
public static class Bean4 {
private String seqno;
@@ -410,7 +456,7 @@ public class CopierTest {
}
}
public class Bean5 {
public static class Bean5 {
private int seqno;