Inners
This commit is contained in:
@@ -25,7 +25,7 @@ import org.redkale.util.*;
|
|||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
|
public class JsonConvert extends TextConvert<JsonReader, JsonWriter> {
|
||||||
|
|
||||||
public static final Type TYPE_MAP_STRING_STRING = new TypeToken<java.util.HashMap<String, String>>() {
|
public static final Type TYPE_MAP_STRING_STRING = new TypeToken<java.util.Map<String, String>>() {
|
||||||
}.getType();
|
}.getType();
|
||||||
|
|
||||||
public static final Type TYPE_LIST_STRING = new TypeToken<java.util.List<String>>() {
|
public static final Type TYPE_LIST_STRING = new TypeToken<java.util.List<String>>() {
|
||||||
|
|||||||
@@ -251,7 +251,7 @@ public interface Copier<S, D> extends BiFunction<S, D, D> {
|
|||||||
public static <S, D, C extends Collection> Function<Collection<S>, Collection<D>> funcCollection(final Class<S> srcClass, final Class<D> destClass,
|
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) {
|
final int options, final Class<C> collectionClass) {
|
||||||
if (destClass == srcClass) {
|
if (destClass == srcClass) {
|
||||||
return CopierInner.funcListOneCaches
|
return Inners.CopierInner.copierFuncListOneCaches
|
||||||
.computeIfAbsent(collectionClass, t -> new ConcurrentHashMap<>())
|
.computeIfAbsent(collectionClass, t -> new ConcurrentHashMap<>())
|
||||||
.computeIfAbsent(options, t -> new ConcurrentHashMap<>())
|
.computeIfAbsent(options, t -> new ConcurrentHashMap<>())
|
||||||
.computeIfAbsent(srcClass, v -> {
|
.computeIfAbsent(srcClass, v -> {
|
||||||
@@ -273,7 +273,7 @@ public interface Copier<S, D> extends BiFunction<S, D, D> {
|
|||||||
return funcList;
|
return funcList;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
return CopierInner.funcListTwoCaches
|
return Inners.CopierInner.copierFuncListTwoCaches
|
||||||
.computeIfAbsent(collectionClass, t -> new ConcurrentHashMap<>())
|
.computeIfAbsent(collectionClass, t -> new ConcurrentHashMap<>())
|
||||||
.computeIfAbsent(options, t -> new ConcurrentHashMap<>())
|
.computeIfAbsent(options, t -> new ConcurrentHashMap<>())
|
||||||
.computeIfAbsent(srcClass, t -> new ConcurrentHashMap<>())
|
.computeIfAbsent(srcClass, t -> new ConcurrentHashMap<>())
|
||||||
@@ -311,7 +311,7 @@ public interface Copier<S, D> extends BiFunction<S, D, D> {
|
|||||||
*/
|
*/
|
||||||
public static <S, D> Function<S, D> func(final Class<S> srcClass, final Class<D> destClass, final int options) {
|
public static <S, D> Function<S, D> func(final Class<S> srcClass, final Class<D> destClass, final int options) {
|
||||||
if (destClass == srcClass) {
|
if (destClass == srcClass) {
|
||||||
return CopierInner.funcOneCaches
|
return Inners.CopierInner.copierFuncOneCaches
|
||||||
.computeIfAbsent(options, t -> new ConcurrentHashMap<>())
|
.computeIfAbsent(options, t -> new ConcurrentHashMap<>())
|
||||||
.computeIfAbsent(srcClass, v -> {
|
.computeIfAbsent(srcClass, v -> {
|
||||||
Copier<S, D> copier = load(srcClass, destClass, options);
|
Copier<S, D> copier = load(srcClass, destClass, options);
|
||||||
@@ -320,7 +320,7 @@ public interface Copier<S, D> extends BiFunction<S, D, D> {
|
|||||||
return func;
|
return func;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
return CopierInner.funcTwoCaches
|
return Inners.CopierInner.copierFuncTwoCaches
|
||||||
.computeIfAbsent(options, t -> new ConcurrentHashMap<>())
|
.computeIfAbsent(options, t -> new ConcurrentHashMap<>())
|
||||||
.computeIfAbsent(srcClass, t -> new ConcurrentHashMap<>())
|
.computeIfAbsent(srcClass, t -> new ConcurrentHashMap<>())
|
||||||
.computeIfAbsent(destClass, v -> {
|
.computeIfAbsent(destClass, v -> {
|
||||||
@@ -345,11 +345,11 @@ public interface Copier<S, D> extends BiFunction<S, D, D> {
|
|||||||
*/
|
*/
|
||||||
public static <S, D> Copier<S, D> load(final Class<S> srcClass, final Class<D> destClass, final int options) {
|
public static <S, D> Copier<S, D> load(final Class<S> srcClass, final Class<D> destClass, final int options) {
|
||||||
if (destClass == srcClass) {
|
if (destClass == srcClass) {
|
||||||
return CopierInner.copierOneCaches
|
return Inners.CopierInner.copierOneCaches
|
||||||
.computeIfAbsent(options, t -> new ConcurrentHashMap<>())
|
.computeIfAbsent(options, t -> new ConcurrentHashMap<>())
|
||||||
.computeIfAbsent(srcClass, v -> create(srcClass, destClass, options));
|
.computeIfAbsent(srcClass, v -> create(srcClass, destClass, options));
|
||||||
} else {
|
} else {
|
||||||
return CopierInner.copierTwoCaches
|
return Inners.CopierInner.copierTwoCaches
|
||||||
.computeIfAbsent(options, t -> new ConcurrentHashMap<>())
|
.computeIfAbsent(options, t -> new ConcurrentHashMap<>())
|
||||||
.computeIfAbsent(srcClass, t -> new ConcurrentHashMap<>())
|
.computeIfAbsent(srcClass, t -> new ConcurrentHashMap<>())
|
||||||
.computeIfAbsent(destClass, v -> create(srcClass, destClass, options));
|
.computeIfAbsent(destClass, v -> create(srcClass, destClass, options));
|
||||||
@@ -1124,28 +1124,4 @@ public interface Copier<S, D> extends BiFunction<S, D, D> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static class CopierInner {
|
|
||||||
|
|
||||||
static final ConcurrentHashMap<Integer, ConcurrentHashMap<Class, Copier>> copierOneCaches = new ConcurrentHashMap();
|
|
||||||
|
|
||||||
static final ConcurrentHashMap<Integer, ConcurrentHashMap<Class, ConcurrentHashMap<Class, Copier>>> copierTwoCaches = new ConcurrentHashMap();
|
|
||||||
|
|
||||||
static final ConcurrentHashMap<Integer, ConcurrentHashMap<Class, Function>> funcOneCaches = new ConcurrentHashMap();
|
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,15 +6,11 @@ package org.redkale.util;
|
|||||||
|
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.lang.reflect.*;
|
import java.lang.reflect.*;
|
||||||
import java.math.*;
|
|
||||||
import java.net.*;
|
import java.net.*;
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.util.AbstractMap.SimpleEntry;
|
import java.util.AbstractMap.SimpleEntry;
|
||||||
import java.util.*;
|
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.stream.Stream;
|
|
||||||
import org.redkale.annotation.ConstructorParameters;
|
import org.redkale.annotation.ConstructorParameters;
|
||||||
import org.redkale.asm.*;
|
import org.redkale.asm.*;
|
||||||
import static org.redkale.asm.Opcodes.*;
|
import static org.redkale.asm.Opcodes.*;
|
||||||
@@ -102,22 +98,22 @@ public interface Creator<T> {
|
|||||||
* @return IntFunction
|
* @return IntFunction
|
||||||
*/
|
*/
|
||||||
public static <T> IntFunction<T[]> funcArray(final Class<T> type) {
|
public static <T> IntFunction<T[]> funcArray(final Class<T> type) {
|
||||||
return CreatorInner.arrayCacheMap.computeIfAbsent(type, CreatorInner::createArrayFunction);
|
return Inners.CreatorInner.arrayCacheMap.computeIfAbsent(type, Inners.CreatorInner::createArrayFunction);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> Creator<T> load(Class<T> clazz) {
|
public static <T> Creator<T> load(Class<T> clazz) {
|
||||||
return CreatorInner.creatorCacheMap.computeIfAbsent(clazz, v -> create(clazz));
|
return Inners.CreatorInner.creatorCacheMap.computeIfAbsent(clazz, v -> create(clazz));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> Creator<T> register(Class<T> clazz, final Supplier<T> supplier) {
|
public static <T> Creator<T> register(Class<T> clazz, final Supplier<T> supplier) {
|
||||||
Creator<T> creator = (Object... params) -> supplier.get();
|
Creator<T> creator = (Object... params) -> supplier.get();
|
||||||
CreatorInner.creatorCacheMap.put(clazz, creator);
|
Inners.CreatorInner.creatorCacheMap.put(clazz, creator);
|
||||||
return creator;
|
return creator;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> Creator<T> register(final LambdaSupplier<T> supplier) {
|
public static <T> Creator<T> register(final LambdaSupplier<T> supplier) {
|
||||||
Creator<T> creator = (Object... params) -> supplier.get();
|
Creator<T> creator = (Object... params) -> supplier.get();
|
||||||
CreatorInner.creatorCacheMap.put(LambdaSupplier.readClass(supplier), creator);
|
Inners.CreatorInner.creatorCacheMap.put(LambdaSupplier.readClass(supplier), creator);
|
||||||
return creator;
|
return creator;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -231,7 +227,7 @@ public interface Creator<T> {
|
|||||||
} else if (Future.class.isAssignableFrom(clazz) && clazz.isAssignableFrom(CompletableFuture.class)) {
|
} else if (Future.class.isAssignableFrom(clazz) && clazz.isAssignableFrom(CompletableFuture.class)) {
|
||||||
clazz = (Class<T>) CompletableFuture.class;
|
clazz = (Class<T>) CompletableFuture.class;
|
||||||
}
|
}
|
||||||
Creator creator = CreatorInner.creatorCacheMap.get(clazz);
|
Creator creator = Inners.CreatorInner.creatorCacheMap.get(clazz);
|
||||||
if (creator != null) {
|
if (creator != null) {
|
||||||
return creator;
|
return creator;
|
||||||
}
|
}
|
||||||
@@ -292,7 +288,7 @@ public interface Creator<T> {
|
|||||||
if (cp == null) {
|
if (cp == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
SimpleEntry<String, Class>[] fields = CreatorInner.getConstructorField(clazz, c.getParameterCount(), cp.value());
|
SimpleEntry<String, Class>[] fields = Inners.CreatorInner.getConstructorField(clazz, c.getParameterCount(), cp.value());
|
||||||
if (fields != null) {
|
if (fields != null) {
|
||||||
constructor0 = c;
|
constructor0 = c;
|
||||||
constructorParameters0 = fields;
|
constructorParameters0 = fields;
|
||||||
@@ -314,7 +310,7 @@ public interface Creator<T> {
|
|||||||
//优先参数最多的构造函数
|
//优先参数最多的构造函数
|
||||||
cs.sort((o1, o2) -> o2.getParameterCount() - o1.getParameterCount());
|
cs.sort((o1, o2) -> o2.getParameterCount() - o1.getParameterCount());
|
||||||
for (Constructor c : cs) {
|
for (Constructor c : cs) {
|
||||||
SimpleEntry<String, Class>[] fields = CreatorInner.getConstructorField(clazz, c.getParameterCount(), Type.getConstructorDescriptor(c));
|
SimpleEntry<String, Class>[] fields = Inners.CreatorInner.getConstructorField(clazz, c.getParameterCount(), Type.getConstructorDescriptor(c));
|
||||||
if (fields != null) {
|
if (fields != null) {
|
||||||
constructor0 = c;
|
constructor0 = c;
|
||||||
constructorParameters0 = fields;
|
constructorParameters0 = fields;
|
||||||
@@ -331,7 +327,7 @@ public interface Creator<T> {
|
|||||||
if (cp == null) {
|
if (cp == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
SimpleEntry<String, Class>[] fields = CreatorInner.getConstructorField(clazz, c.getParameterCount(), cp.value());
|
SimpleEntry<String, Class>[] fields = Inners.CreatorInner.getConstructorField(clazz, c.getParameterCount(), cp.value());
|
||||||
if (fields != null) {
|
if (fields != null) {
|
||||||
constructor0 = c;
|
constructor0 = c;
|
||||||
constructorParameters0 = fields;
|
constructorParameters0 = fields;
|
||||||
@@ -356,7 +352,7 @@ public interface Creator<T> {
|
|||||||
//优先参数最多的构造函数
|
//优先参数最多的构造函数
|
||||||
cs.sort((o1, o2) -> o2.getParameterCount() - o1.getParameterCount());
|
cs.sort((o1, o2) -> o2.getParameterCount() - o1.getParameterCount());
|
||||||
for (Constructor c : cs) {
|
for (Constructor c : cs) {
|
||||||
SimpleEntry<String, Class>[] fields = CreatorInner.getConstructorField(clazz, c.getParameterCount(), Type.getConstructorDescriptor(c));
|
SimpleEntry<String, Class>[] fields = Inners.CreatorInner.getConstructorField(clazz, c.getParameterCount(), Type.getConstructorDescriptor(c));
|
||||||
if (fields != null) {
|
if (fields != null) {
|
||||||
constructor0 = c;
|
constructor0 = c;
|
||||||
constructorParameters0 = fields;
|
constructorParameters0 = fields;
|
||||||
@@ -581,252 +577,4 @@ public interface Creator<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
static class CreatorInner {
|
|
||||||
|
|
||||||
static final Logger logger = Logger.getLogger(Creator.class.getSimpleName());
|
|
||||||
|
|
||||||
static final Map<Class, Creator> creatorCacheMap = new HashMap<>();
|
|
||||||
|
|
||||||
static final Map<Class, IntFunction> arrayCacheMap = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
static {
|
|
||||||
creatorCacheMap.put(Object.class, p -> new Object());
|
|
||||||
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"})
|
|
||||||
public Map.Entry create(Object... params) {
|
|
||||||
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>() {
|
|
||||||
@Override
|
|
||||||
@ConstructorParameters({"key", "value"})
|
|
||||||
public AbstractMap.SimpleEntry create(Object... params) {
|
|
||||||
return new AbstractMap.SimpleEntry(params[0], params[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class[] paramTypes() {
|
|
||||||
return new Class[]{Object.class, Object.class};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
arrayCacheMap.put(int.class, t -> new int[t]);
|
|
||||||
arrayCacheMap.put(byte.class, t -> new byte[t]);
|
|
||||||
arrayCacheMap.put(long.class, t -> new long[t]);
|
|
||||||
arrayCacheMap.put(String.class, t -> new String[t]);
|
|
||||||
arrayCacheMap.put(Object.class, t -> new Object[t]);
|
|
||||||
arrayCacheMap.put(boolean.class, t -> new boolean[t]);
|
|
||||||
arrayCacheMap.put(short.class, t -> new short[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]);
|
|
||||||
arrayCacheMap.put(CompletableFuture.class, t -> new CompletableFuture[t]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static class SimpleClassVisitor extends ClassVisitor {
|
|
||||||
|
|
||||||
private final String constructorDesc;
|
|
||||||
|
|
||||||
private final List<String> fieldNames;
|
|
||||||
|
|
||||||
private boolean started;
|
|
||||||
|
|
||||||
public SimpleClassVisitor(int api, List<String> fieldNames, String constructorDesc) {
|
|
||||||
super(api);
|
|
||||||
this.fieldNames = fieldNames;
|
|
||||||
this.constructorDesc = constructorDesc;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
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 (constructorDesc != null && !constructorDesc.equals(desc)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (this.started) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
this.started = true;
|
|
||||||
//返回的List中参数列表可能会比方法参数量多,因为方法内的临时变量也会存入list中, 所以需要list的元素集合比方法的参数多
|
|
||||||
return new MethodVisitor(Opcodes.ASM6) {
|
|
||||||
@Override
|
|
||||||
public void visitLocalVariable(String name, String description, String signature, Label start, Label end, int index) {
|
|
||||||
if (index < 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int size = fieldNames.size();
|
|
||||||
//index不会按顺序执行的
|
|
||||||
if (index > size) {
|
|
||||||
for (int i = size; i < index; i++) {
|
|
||||||
fieldNames.add(" ");
|
|
||||||
}
|
|
||||||
fieldNames.set(index - 1, name);
|
|
||||||
}
|
|
||||||
fieldNames.set(index - 1, name);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SimpleEntry<String, Class>[] getConstructorField(Class clazz, int paramCount, String constructorDesc) {
|
|
||||||
String n = clazz.getName();
|
|
||||||
InputStream in = clazz.getResourceAsStream(n.substring(n.lastIndexOf('.') + 1) + ".class");
|
|
||||||
if (in == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
|
|
||||||
byte[] bytes = new byte[1024];
|
|
||||||
int pos;
|
|
||||||
try {
|
|
||||||
while ((pos = in.read(bytes)) != -1) {
|
|
||||||
out.write(bytes, 0, pos);
|
|
||||||
}
|
|
||||||
in.close();
|
|
||||||
} catch (IOException io) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
final List<String> fieldNames = new ArrayList<>();
|
|
||||||
new ClassReader(out.toByteArray()).accept(new SimpleClassVisitor(Opcodes.ASM6, fieldNames, constructorDesc), 0);
|
|
||||||
while (fieldNames.remove(" ")); //删掉空元素
|
|
||||||
if (fieldNames.isEmpty()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (paramCount == fieldNames.size()) {
|
|
||||||
return getConstructorField(clazz, paramCount, fieldNames.toArray(new String[fieldNames.size()]));
|
|
||||||
} else {
|
|
||||||
String[] fs = new String[paramCount];
|
|
||||||
for (int i = 0; i < fs.length; i++) {
|
|
||||||
fs[i] = fieldNames.get(i);
|
|
||||||
}
|
|
||||||
return getConstructorField(clazz, paramCount, fs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SimpleEntry<String, Class>[] getConstructorField(Class clazz, int paramCount, String[] names) {
|
|
||||||
SimpleEntry<String, Class>[] se = new SimpleEntry[names.length];
|
|
||||||
for (int i = 0; i < names.length; i++) { //查询参数名对应的Field
|
|
||||||
try {
|
|
||||||
Field field = clazz.getDeclaredField(names[i]);
|
|
||||||
se[i] = new SimpleEntry<>(field.getName(), field.getType());
|
|
||||||
} catch (NoSuchFieldException fe) {
|
|
||||||
Class cz = clazz;
|
|
||||||
Field field = null;
|
|
||||||
while ((cz = cz.getSuperclass()) != Object.class) {
|
|
||||||
try {
|
|
||||||
field = cz.getDeclaredField(names[i]);
|
|
||||||
break;
|
|
||||||
} catch (NoSuchFieldException nsfe) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (field == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
se[i] = new SimpleEntry<>(field.getName(), field.getType());
|
|
||||||
} catch (Exception e) {
|
|
||||||
if (logger.isLoggable(Level.FINE)) {
|
|
||||||
logger.log(Level.FINE, clazz + " getConstructorField error", e);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return se;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SimpleEntry<String, Class>[] getConstructorField(Class clazz, int paramCount, Parameter[] params) {
|
|
||||||
SimpleEntry<String, Class>[] se = new SimpleEntry[params.length];
|
|
||||||
for (int i = 0; i < params.length; i++) { //查询参数名对应的Field
|
|
||||||
try {
|
|
||||||
Field field = clazz.getDeclaredField(params[i].getName());
|
|
||||||
se[i] = new SimpleEntry<>(field.getName(), field.getType());
|
|
||||||
} catch (Exception e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return se;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> IntFunction<T[]> createArrayFunction(final Class<T> clazz) {
|
|
||||||
final String interName = clazz.getName().replace('.', '/');
|
|
||||||
final String interDesc = Type.getDescriptor(clazz);
|
|
||||||
final ClassLoader loader = clazz.getClassLoader();
|
|
||||||
final String newDynName = "org/redkaledyn/creator/_DynArrayFunction__" + clazz.getName().replace('.', '_').replace('$', '_');
|
|
||||||
try {
|
|
||||||
Class clz = RedkaleClassLoader.findDynClass(newDynName.replace('/', '.'));
|
|
||||||
return (IntFunction) (clz == null ? loader.loadClass(newDynName.replace('/', '.')) : clz).getDeclaredConstructor().newInstance();
|
|
||||||
} catch (Throwable ex) {
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------------------------------------------
|
|
||||||
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
|
|
||||||
MethodVisitor mv;
|
|
||||||
cw.visit(V11, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynName, "Ljava/lang/Object;Ljava/util/function/IntFunction<[" + interDesc + ">;", "java/lang/Object", new String[]{"java/util/function/IntFunction"});
|
|
||||||
|
|
||||||
{//IntFunction自身的构造方法
|
|
||||||
mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
|
|
||||||
mv.visitVarInsn(ALOAD, 0);
|
|
||||||
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
|
|
||||||
mv.visitInsn(RETURN);
|
|
||||||
mv.visitMaxs(1, 1);
|
|
||||||
mv.visitEnd();
|
|
||||||
}
|
|
||||||
{//apply 方法
|
|
||||||
mv = cw.visitMethod(ACC_PUBLIC, "apply", "(I)[" + interDesc, null, null);
|
|
||||||
mv.visitVarInsn(ILOAD, 1);
|
|
||||||
mv.visitTypeInsn(ANEWARRAY, interName);
|
|
||||||
mv.visitInsn(ARETURN);
|
|
||||||
mv.visitMaxs(1, 2);
|
|
||||||
mv.visitEnd();
|
|
||||||
}
|
|
||||||
{ //虚拟 apply 方法
|
|
||||||
mv = cw.visitMethod(ACC_PUBLIC + ACC_BRIDGE + ACC_SYNTHETIC, "apply", "(I)Ljava/lang/Object;", null, null);
|
|
||||||
mv.visitVarInsn(ALOAD, 0);
|
|
||||||
mv.visitVarInsn(ILOAD, 1);
|
|
||||||
mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "apply", "(I)[" + interDesc, false);
|
|
||||||
mv.visitInsn(ARETURN);
|
|
||||||
mv.visitMaxs(2, 2);
|
|
||||||
mv.visitEnd();
|
|
||||||
}
|
|
||||||
cw.visitEnd();
|
|
||||||
final byte[] bytes = cw.toByteArray();
|
|
||||||
try {
|
|
||||||
Class<?> resultClazz = new ClassLoader(loader) {
|
|
||||||
public final Class<?> loadClass(String name, byte[] b) {
|
|
||||||
return defineClass(name, b, 0, b.length);
|
|
||||||
}
|
|
||||||
}.loadClass(newDynName.replace('/', '.'), bytes);
|
|
||||||
RedkaleClassLoader.putDynClass(newDynName.replace('/', '.'), bytes, resultClazz);
|
|
||||||
RedkaleClassLoader.putReflectionDeclaredConstructors(resultClazz, newDynName.replace('/', '.'));
|
|
||||||
return (IntFunction<T[]>) resultClazz.getDeclaredConstructor().newInstance();
|
|
||||||
} catch (Throwable ex) {
|
|
||||||
//ex.printStackTrace(); //一般不会发生, native-image在没有预编译情况下会报错
|
|
||||||
return t -> (T[]) Array.newInstance(clazz, t);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
304
src/main/java/org/redkale/util/Inners.java
Normal file
304
src/main/java/org/redkale/util/Inners.java
Normal file
@@ -0,0 +1,304 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
package org.redkale.util;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.lang.reflect.*;
|
||||||
|
import java.math.*;
|
||||||
|
import java.net.*;
|
||||||
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.*;
|
||||||
|
import java.util.function.*;
|
||||||
|
import java.util.logging.*;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
import org.redkale.asm.*;
|
||||||
|
import static org.redkale.asm.Opcodes.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author zhangjx
|
||||||
|
*/
|
||||||
|
class Inners {
|
||||||
|
|
||||||
|
private Inners() {
|
||||||
|
}
|
||||||
|
|
||||||
|
static class CreatorInner {
|
||||||
|
|
||||||
|
static final Logger logger = Logger.getLogger(Creator.class.getSimpleName());
|
||||||
|
|
||||||
|
static final Map<Class, Creator> creatorCacheMap = new HashMap<>();
|
||||||
|
|
||||||
|
static final Map<Class, IntFunction> arrayCacheMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
creatorCacheMap.put(Object.class, p -> new Object());
|
||||||
|
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
|
||||||
|
@org.redkale.annotation.ConstructorParameters({"key", "value"})
|
||||||
|
public Map.Entry create(Object... params) {
|
||||||
|
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>() {
|
||||||
|
@Override
|
||||||
|
@org.redkale.annotation.ConstructorParameters({"key", "value"})
|
||||||
|
public AbstractMap.SimpleEntry create(Object... params) {
|
||||||
|
return new AbstractMap.SimpleEntry(params[0], params[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class[] paramTypes() {
|
||||||
|
return new Class[]{Object.class, Object.class};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
arrayCacheMap.put(int.class, t -> new int[t]);
|
||||||
|
arrayCacheMap.put(byte.class, t -> new byte[t]);
|
||||||
|
arrayCacheMap.put(long.class, t -> new long[t]);
|
||||||
|
arrayCacheMap.put(String.class, t -> new String[t]);
|
||||||
|
arrayCacheMap.put(Object.class, t -> new Object[t]);
|
||||||
|
arrayCacheMap.put(boolean.class, t -> new boolean[t]);
|
||||||
|
arrayCacheMap.put(short.class, t -> new short[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]);
|
||||||
|
arrayCacheMap.put(CompletableFuture.class, t -> new CompletableFuture[t]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static class SimpleClassVisitor extends ClassVisitor {
|
||||||
|
|
||||||
|
private final String constructorDesc;
|
||||||
|
|
||||||
|
private final List<String> fieldNames;
|
||||||
|
|
||||||
|
private boolean started;
|
||||||
|
|
||||||
|
public SimpleClassVisitor(int api, List<String> fieldNames, String constructorDesc) {
|
||||||
|
super(api);
|
||||||
|
this.fieldNames = fieldNames;
|
||||||
|
this.constructorDesc = constructorDesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
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 (constructorDesc != null && !constructorDesc.equals(desc)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (this.started) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
this.started = true;
|
||||||
|
//返回的List中参数列表可能会比方法参数量多,因为方法内的临时变量也会存入list中, 所以需要list的元素集合比方法的参数多
|
||||||
|
return new MethodVisitor(Opcodes.ASM6) {
|
||||||
|
@Override
|
||||||
|
public void visitLocalVariable(String name, String description, String signature, Label start, Label end, int index) {
|
||||||
|
if (index < 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int size = fieldNames.size();
|
||||||
|
//index不会按顺序执行的
|
||||||
|
if (index > size) {
|
||||||
|
for (int i = size; i < index; i++) {
|
||||||
|
fieldNames.add(" ");
|
||||||
|
}
|
||||||
|
fieldNames.set(index - 1, name);
|
||||||
|
}
|
||||||
|
fieldNames.set(index - 1, name);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AbstractMap.SimpleEntry<String, Class>[] getConstructorField(Class clazz, int paramCount, String constructorDesc) {
|
||||||
|
String n = clazz.getName();
|
||||||
|
InputStream in = clazz.getResourceAsStream(n.substring(n.lastIndexOf('.') + 1) + ".class");
|
||||||
|
if (in == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
|
||||||
|
byte[] bytes = new byte[1024];
|
||||||
|
int pos;
|
||||||
|
try {
|
||||||
|
while ((pos = in.read(bytes)) != -1) {
|
||||||
|
out.write(bytes, 0, pos);
|
||||||
|
}
|
||||||
|
in.close();
|
||||||
|
} catch (IOException io) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
final List<String> fieldNames = new ArrayList<>();
|
||||||
|
new ClassReader(out.toByteArray()).accept(new SimpleClassVisitor(Opcodes.ASM6, fieldNames, constructorDesc), 0);
|
||||||
|
while (fieldNames.remove(" ")); //删掉空元素
|
||||||
|
if (fieldNames.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (paramCount == fieldNames.size()) {
|
||||||
|
return getConstructorField(clazz, paramCount, fieldNames.toArray(new String[fieldNames.size()]));
|
||||||
|
} else {
|
||||||
|
String[] fs = new String[paramCount];
|
||||||
|
for (int i = 0; i < fs.length; i++) {
|
||||||
|
fs[i] = fieldNames.get(i);
|
||||||
|
}
|
||||||
|
return getConstructorField(clazz, paramCount, fs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AbstractMap.SimpleEntry<String, Class>[] getConstructorField(Class clazz, int paramCount, String[] names) {
|
||||||
|
AbstractMap.SimpleEntry<String, Class>[] se = new AbstractMap.SimpleEntry[names.length];
|
||||||
|
for (int i = 0; i < names.length; i++) { //查询参数名对应的Field
|
||||||
|
try {
|
||||||
|
Field field = clazz.getDeclaredField(names[i]);
|
||||||
|
se[i] = new AbstractMap.SimpleEntry<>(field.getName(), field.getType());
|
||||||
|
} catch (NoSuchFieldException fe) {
|
||||||
|
Class cz = clazz;
|
||||||
|
Field field = null;
|
||||||
|
while ((cz = cz.getSuperclass()) != Object.class) {
|
||||||
|
try {
|
||||||
|
field = cz.getDeclaredField(names[i]);
|
||||||
|
break;
|
||||||
|
} catch (NoSuchFieldException nsfe) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (field == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
se[i] = new AbstractMap.SimpleEntry<>(field.getName(), field.getType());
|
||||||
|
} catch (Exception e) {
|
||||||
|
if (logger.isLoggable(Level.FINE)) {
|
||||||
|
logger.log(Level.FINE, clazz + " getConstructorField error", e);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return se;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AbstractMap.SimpleEntry<String, Class>[] getConstructorField(Class clazz, int paramCount, Parameter[] params) {
|
||||||
|
AbstractMap.SimpleEntry<String, Class>[] se = new AbstractMap.SimpleEntry[params.length];
|
||||||
|
for (int i = 0; i < params.length; i++) { //查询参数名对应的Field
|
||||||
|
try {
|
||||||
|
Field field = clazz.getDeclaredField(params[i].getName());
|
||||||
|
se[i] = new AbstractMap.SimpleEntry<>(field.getName(), field.getType());
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return se;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> IntFunction<T[]> createArrayFunction(final Class<T> clazz) {
|
||||||
|
final String interName = clazz.getName().replace('.', '/');
|
||||||
|
final String interDesc = org.redkale.asm.Type.getDescriptor(clazz);
|
||||||
|
final ClassLoader loader = clazz.getClassLoader();
|
||||||
|
final String newDynName = "org/redkaledyn/creator/_DynArrayFunction__" + clazz.getName().replace('.', '_').replace('$', '_');
|
||||||
|
try {
|
||||||
|
Class clz = RedkaleClassLoader.findDynClass(newDynName.replace('/', '.'));
|
||||||
|
return (IntFunction) (clz == null ? loader.loadClass(newDynName.replace('/', '.')) : clz).getDeclaredConstructor().newInstance();
|
||||||
|
} catch (Throwable ex) {
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------
|
||||||
|
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
|
||||||
|
MethodVisitor mv;
|
||||||
|
cw.visit(V11, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynName, "Ljava/lang/Object;Ljava/util/function/IntFunction<[" + interDesc + ">;", "java/lang/Object", new String[]{"java/util/function/IntFunction"});
|
||||||
|
|
||||||
|
{//IntFunction自身的构造方法
|
||||||
|
mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null);
|
||||||
|
mv.visitVarInsn(ALOAD, 0);
|
||||||
|
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
|
||||||
|
mv.visitInsn(RETURN);
|
||||||
|
mv.visitMaxs(1, 1);
|
||||||
|
mv.visitEnd();
|
||||||
|
}
|
||||||
|
{//apply 方法
|
||||||
|
mv = cw.visitMethod(ACC_PUBLIC, "apply", "(I)[" + interDesc, null, null);
|
||||||
|
mv.visitVarInsn(ILOAD, 1);
|
||||||
|
mv.visitTypeInsn(ANEWARRAY, interName);
|
||||||
|
mv.visitInsn(ARETURN);
|
||||||
|
mv.visitMaxs(1, 2);
|
||||||
|
mv.visitEnd();
|
||||||
|
}
|
||||||
|
{ //虚拟 apply 方法
|
||||||
|
mv = cw.visitMethod(ACC_PUBLIC + ACC_BRIDGE + ACC_SYNTHETIC, "apply", "(I)Ljava/lang/Object;", null, null);
|
||||||
|
mv.visitVarInsn(ALOAD, 0);
|
||||||
|
mv.visitVarInsn(ILOAD, 1);
|
||||||
|
mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "apply", "(I)[" + interDesc, false);
|
||||||
|
mv.visitInsn(ARETURN);
|
||||||
|
mv.visitMaxs(2, 2);
|
||||||
|
mv.visitEnd();
|
||||||
|
}
|
||||||
|
cw.visitEnd();
|
||||||
|
final byte[] bytes = cw.toByteArray();
|
||||||
|
try {
|
||||||
|
Class<?> resultClazz = new ClassLoader(loader) {
|
||||||
|
public final Class<?> loadClass(String name, byte[] b) {
|
||||||
|
return defineClass(name, b, 0, b.length);
|
||||||
|
}
|
||||||
|
}.loadClass(newDynName.replace('/', '.'), bytes);
|
||||||
|
RedkaleClassLoader.putDynClass(newDynName.replace('/', '.'), bytes, resultClazz);
|
||||||
|
RedkaleClassLoader.putReflectionDeclaredConstructors(resultClazz, newDynName.replace('/', '.'));
|
||||||
|
return (IntFunction<T[]>) resultClazz.getDeclaredConstructor().newInstance();
|
||||||
|
} catch (Throwable ex) {
|
||||||
|
//ex.printStackTrace(); //一般不会发生, native-image在没有预编译情况下会报错
|
||||||
|
return t -> (T[]) Array.newInstance(clazz, t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class CopierInner {
|
||||||
|
|
||||||
|
static final ConcurrentHashMap<Integer, ConcurrentHashMap<Class, Copier>> copierOneCaches = new ConcurrentHashMap();
|
||||||
|
|
||||||
|
static final ConcurrentHashMap<Integer, ConcurrentHashMap<Class, ConcurrentHashMap<Class, Copier>>> copierTwoCaches = new ConcurrentHashMap();
|
||||||
|
|
||||||
|
static final ConcurrentHashMap<Integer, ConcurrentHashMap<Class, Function>> copierFuncOneCaches = new ConcurrentHashMap();
|
||||||
|
|
||||||
|
static final ConcurrentHashMap<Integer, ConcurrentHashMap<Class, ConcurrentHashMap<Class, Function>>> copierFuncTwoCaches = new ConcurrentHashMap();
|
||||||
|
|
||||||
|
static final ConcurrentHashMap<Class, ConcurrentHashMap<Integer, ConcurrentHashMap<Class, Function>>> copierFuncListOneCaches = new ConcurrentHashMap();
|
||||||
|
|
||||||
|
static final ConcurrentHashMap<Class, ConcurrentHashMap<Integer, ConcurrentHashMap<Class, ConcurrentHashMap<Class, Function>>>> copierFuncListTwoCaches = new ConcurrentHashMap();
|
||||||
|
|
||||||
|
public static void clearCopierCache() {
|
||||||
|
copierOneCaches.clear();
|
||||||
|
copierTwoCaches.clear();
|
||||||
|
copierFuncOneCaches.clear();
|
||||||
|
copierFuncTwoCaches.clear();
|
||||||
|
copierFuncListOneCaches.clear();
|
||||||
|
copierFuncListTwoCaches.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class InvokerInner {
|
||||||
|
|
||||||
|
static final ConcurrentHashMap<Class, ConcurrentHashMap<Method, Invoker>> invokerCaches = new ConcurrentHashMap();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -56,7 +56,7 @@ public interface Invoker<OBJECT_TYPE, RETURN_TYPE> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static <C, T> Invoker<C, T> load(final Class<C> clazz, final Method method) {
|
public static <C, T> Invoker<C, T> load(final Class<C> clazz, final Method method) {
|
||||||
return InvokerInner.caches
|
return Inners.InvokerInner.invokerCaches
|
||||||
.computeIfAbsent(clazz, t -> new ConcurrentHashMap<>())
|
.computeIfAbsent(clazz, t -> new ConcurrentHashMap<>())
|
||||||
.computeIfAbsent(method, v -> create(clazz, method));
|
.computeIfAbsent(method, v -> create(clazz, method));
|
||||||
}
|
}
|
||||||
@@ -190,9 +190,4 @@ public interface Invoker<OBJECT_TYPE, RETURN_TYPE> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static class InvokerInner {
|
|
||||||
|
|
||||||
static final ConcurrentHashMap<Class, ConcurrentHashMap<Method, Invoker>> caches = new ConcurrentHashMap();
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user