新增Copier
This commit is contained in:
@@ -1257,7 +1257,7 @@ public final class Application {
|
||||
if (!sourceConf.getValue(AbstractDataSource.DATA_SOURCE_RESOURCE, "").isEmpty()) {
|
||||
DataSource source = loadDataSource(sourceConf.getValue(AbstractDataSource.DATA_SOURCE_RESOURCE), autoMemory);
|
||||
if (source != null) {
|
||||
if (source instanceof DataMemorySource && DataMemorySource.isSearchType(sourceConf)) {
|
||||
if (source instanceof DataMemorySource && source instanceof SearchSource) {
|
||||
resourceFactory.register(sourceName, SearchSource.class, source);
|
||||
} else {
|
||||
resourceFactory.register(sourceName, DataSource.class, source);
|
||||
@@ -1271,7 +1271,7 @@ public final class Application {
|
||||
try {
|
||||
DataSource source = AbstractDataSource.createDataSource(serverClassLoader, resourceFactory, sourceConf, sourceName, compileMode);
|
||||
dataSources.add(source);
|
||||
if (source instanceof DataMemorySource && DataMemorySource.isSearchType(sourceConf)) {
|
||||
if (source instanceof DataMemorySource && source instanceof SearchSource) {
|
||||
resourceFactory.register(sourceName, SearchSource.class, source);
|
||||
} else {
|
||||
resourceFactory.register(sourceName, DataSource.class, source);
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.redkale.net.WorkThread;
|
||||
import org.redkale.persistence.Entity;
|
||||
import org.redkale.service.*;
|
||||
import org.redkale.util.*;
|
||||
import static org.redkale.util.Utility.isEmpty;
|
||||
|
||||
/**
|
||||
* DataSource的S抽象实现类 <br>
|
||||
@@ -121,6 +122,8 @@ public abstract class AbstractDataSource extends AbstractService implements Data
|
||||
@Resource(name = RESNAME_APP_EXECUTOR, required = false)
|
||||
private ExecutorService sourceExecutor;
|
||||
|
||||
protected String name;
|
||||
|
||||
@Override
|
||||
public void init(AnyValue conf) {
|
||||
super.init(conf);
|
||||
@@ -131,6 +134,11 @@ public abstract class AbstractDataSource extends AbstractService implements Data
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String resourceName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@ResourceListener
|
||||
public abstract void onResourceChange(ResourceEvent[] events);
|
||||
|
||||
@@ -148,7 +156,7 @@ public abstract class AbstractDataSource extends AbstractService implements Data
|
||||
serverClassLoader = Thread.currentThread().getContextClassLoader();
|
||||
}
|
||||
String classVal = sourceConf.getValue("type");
|
||||
if (classVal == null || classVal.isEmpty()) {
|
||||
if (isEmpty(classVal)) {
|
||||
if (DataJdbcSource.acceptsConf(sourceConf)) {
|
||||
source = new DataJdbcSource();
|
||||
} else {
|
||||
|
||||
@@ -48,8 +48,6 @@ public abstract class AbstractDataSqlSource extends AbstractDataSource implement
|
||||
|
||||
protected final Logger logger = Logger.getLogger(this.getClass().getSimpleName());
|
||||
|
||||
protected String name;
|
||||
|
||||
protected boolean cacheForbidden;
|
||||
|
||||
protected String dbtype;
|
||||
@@ -802,11 +800,6 @@ public abstract class AbstractDataSqlSource extends AbstractDataSource implement
|
||||
return "sql";
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String resourceName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public EntityInfo apply(Class t) {
|
||||
return loadEntityInfo(t);
|
||||
|
||||
@@ -8,7 +8,7 @@ package org.redkale.source;
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.*;
|
||||
import java.util.stream.Stream;
|
||||
import org.redkale.annotation.AutoLoad;
|
||||
import org.redkale.annotation.ResourceListener;
|
||||
import org.redkale.annotation.ResourceType;
|
||||
@@ -33,21 +33,10 @@ import org.redkale.util.*;
|
||||
@AutoLoad(false)
|
||||
@SuppressWarnings("unchecked")
|
||||
@ResourceType(DataSource.class)
|
||||
public class DataMemorySource extends AbstractDataSqlSource implements SearchSource {
|
||||
public class DataMemorySource extends AbstractDataSource {
|
||||
|
||||
public DataMemorySource(String name) {
|
||||
this.name = name;
|
||||
this.cacheForbidden = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int readMaxConns() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int writeMaxConns() {
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Local
|
||||
@@ -64,10 +53,10 @@ public class DataMemorySource extends AbstractDataSqlSource implements SearchSou
|
||||
public static boolean acceptsConf(AnyValue config) {
|
||||
return config.getValue(DATA_SOURCE_URL).startsWith("memory:");
|
||||
}
|
||||
|
||||
public static boolean isSearchType(AnyValue config) {
|
||||
return config.getValue(DATA_SOURCE_URL).startsWith("memory:search");
|
||||
}
|
||||
//
|
||||
// public static boolean isSearchType(AnyValue config) {
|
||||
// return config.getValue(DATA_SOURCE_URL).startsWith("memory:search");
|
||||
// }
|
||||
|
||||
@Local
|
||||
@Override
|
||||
@@ -83,128 +72,353 @@ public class DataMemorySource extends AbstractDataSqlSource implements SearchSou
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final boolean isAsync() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getSimpleName() + "{type=memory, name='" + resourceName() + "'}";
|
||||
}
|
||||
|
||||
@Override
|
||||
public int nativeUpdate(String sql) {
|
||||
public <T> int insert(T... entitys) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] nativeUpdates(String... sqls) {
|
||||
public <T> CompletableFuture<Integer> insertAsync(T... entitys) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <V> V nativeQuery(String sql, BiConsumer<Object, Object> consumer, Function<DataResultSet, V> handler) {
|
||||
public <T> int delete(T... entitys) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int nativeUpdate(String sql, Map<String, Object> params) {
|
||||
public <T> CompletableFuture<Integer> deleteAsync(T... entitys) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <V> V nativeQuery(String sql, BiConsumer<Object, Object> consumer, Function<DataResultSet, V> handler, Map<String, Object> params) {
|
||||
public <T> int delete(Class<T> clazz, Serializable... pks) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String prepareParamSign(int index) {
|
||||
public <T> CompletableFuture<Integer> deleteAsync(Class<T> clazz, Serializable... pks) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> CompletableFuture<Integer> insertDBAsync(EntityInfo<T> info, T... entitys) {
|
||||
public <T> int delete(Class<T> clazz, Flipper flipper, FilterNode node) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> CompletableFuture<Integer> deleteDBAsync(EntityInfo<T> info, String[] tables, Flipper flipper, FilterNode node, Map<String, List<Serializable>> pkmap, String... sqls) {
|
||||
public <T> CompletableFuture<Integer> deleteAsync(Class<T> clazz, Flipper flipper, FilterNode node) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> CompletableFuture<Integer> clearTableDBAsync(EntityInfo<T> info, String[] tables, FilterNode node, String... sqls) {
|
||||
public <T> int clearTable(Class<T> clazz, FilterNode node) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> CompletableFuture<Integer> createTableDBAsync(EntityInfo<T> info, String copyTableSql, Serializable pk, String... sqls) {
|
||||
public <T> CompletableFuture<Integer> clearTableAsync(Class<T> clazz, FilterNode node) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> CompletableFuture<Integer> dropTableDBAsync(EntityInfo<T> info, String[] tables, FilterNode node, String... sqls) {
|
||||
public <T> int createTable(Class<T> clazz, Serializable pk) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> CompletableFuture<Integer> updateEntityDBAsync(EntityInfo<T> info, T... entitys) {
|
||||
public <T> CompletableFuture<Integer> createTableAsync(Class<T> clazz, Serializable pk) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> CompletableFuture<Integer> updateColumnDBAsync(EntityInfo<T> info, Flipper flipper, UpdateSqlInfo sql) {
|
||||
public <T> int dropTable(Class<T> clazz, FilterNode node) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T, N extends Number> CompletableFuture<Map<String, N>> getNumberMapDBAsync(EntityInfo<T> info, String[] tables, String sql, FilterNode node, FilterFuncColumn... columns) {
|
||||
public <T> CompletableFuture<Integer> dropTableAsync(Class<T> clazz, FilterNode node) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> CompletableFuture<Number> getNumberResultDBAsync(EntityInfo<T> info, String[] tables, String sql, FilterFunc func, Number defVal, String column, FilterNode node) {
|
||||
public <T> int update(T... entitys) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T, K extends Serializable, N extends Number> CompletableFuture<Map<K, N>> queryColumnMapDBAsync(EntityInfo<T> info, String[] tables, String sql, String keyColumn, FilterFunc func, String funcColumn, FilterNode node) {
|
||||
public <T> CompletableFuture<Integer> updateAsync(T... entitys) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T, K extends Serializable, N extends Number> CompletableFuture<Map<K[], N[]>> queryColumnMapDBAsync(EntityInfo<T> info, String[] tables, String sql, ColumnNode[] funcNodes, String[] groupByColumns, FilterNode node) {
|
||||
public <T> int updateColumn(Class<T> clazz, Serializable pk, String column, Serializable value) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> CompletableFuture<T> findDBAsync(EntityInfo<T> info, String[] tables, String sql, boolean onlypk, SelectColumn selects, Serializable pk, FilterNode node) {
|
||||
public <T> CompletableFuture<Integer> updateColumnAsync(Class<T> clazz, Serializable pk, String column, Serializable value) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> CompletableFuture<Serializable> findColumnDBAsync(EntityInfo<T> info, String[] tables, String sql, boolean onlypk, String column, Serializable defValue, Serializable pk, FilterNode node) {
|
||||
public <T> int updateColumn(Class<T> clazz, String column, Serializable value, FilterNode node) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> CompletableFuture<Boolean> existsDBAsync(EntityInfo<T> info, String[] tables, String sql, boolean onlypk, Serializable pk, FilterNode node) {
|
||||
public <T> CompletableFuture<Integer> updateColumnAsync(Class<T> clazz, String column, Serializable value, FilterNode node) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> CompletableFuture<Sheet<T>> querySheetDBAsync(EntityInfo<T> info, boolean readcache, boolean needtotal, boolean distinct, SelectColumn selects, Flipper flipper, FilterNode node) {
|
||||
public <T> int updateColumn(Class<T> clazz, Serializable pk, ColumnValue... values) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> int updateMapping(Class<T> clazz, String table) {
|
||||
public <T> CompletableFuture<Integer> updateColumnAsync(Class<T> clazz, Serializable pk, ColumnValue... values) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> CompletableFuture<Integer> updateMappingAsync(Class<T> clazz, String table) {
|
||||
public <T> int updateColumn(Class<T> clazz, FilterNode node, Flipper flipper, ColumnValue... values) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> CompletableFuture<Integer> updateColumnAsync(Class<T> clazz, FilterNode node, Flipper flipper, ColumnValue... values) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> int updateColumn(T entity, FilterNode node, SelectColumn selects) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> CompletableFuture<Integer> updateColumnAsync(T entity, FilterNode node, SelectColumn selects) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Number getNumberResult(Class entityClass, FilterFunc func, Number defVal, String column, FilterNode node) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Number> getNumberResultAsync(Class entityClass, FilterFunc func, Number defVal, String column, FilterNode node) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <N extends Number> Map<String, N> getNumberMap(Class entityClass, FilterNode node, FilterFuncColumn... columns) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <N extends Number> CompletableFuture<Map<String, N>> getNumberMapAsync(Class entityClass, FilterNode node, FilterFuncColumn... columns) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, K extends Serializable, N extends Number> Map<K, N> queryColumnMap(Class<T> entityClass, String keyColumn, FilterFunc func, String funcColumn, FilterNode node) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, K extends Serializable, N extends Number> CompletableFuture<Map<K, N>> queryColumnMapAsync(Class<T> entityClass, String keyColumn, FilterFunc func, String funcColumn, FilterNode node) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, K extends Serializable, N extends Number> Map<K, N[]> queryColumnMap(Class<T> entityClass, ColumnNode[] funcNodes, String groupByColumn, FilterNode node) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, K extends Serializable, N extends Number> CompletableFuture<Map<K, N[]>> queryColumnMapAsync(Class<T> entityClass, ColumnNode[] funcNodes, String groupByColumn, FilterNode node) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, K extends Serializable, N extends Number> Map<K[], N[]> queryColumnMap(Class<T> entityClass, ColumnNode[] funcNodes, String[] groupByColumns, FilterNode node) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, K extends Serializable, N extends Number> CompletableFuture<Map<K[], N[]>> queryColumnMapAsync(Class<T> entityClass, ColumnNode[] funcNodes, String[] groupByColumns, FilterNode node) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T find(Class<T> clazz, SelectColumn selects, Serializable pk) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> CompletableFuture<T> findAsync(Class<T> clazz, SelectColumn selects, Serializable pk) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T[] finds(Class<T> clazz, SelectColumn selects, Serializable... pks) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> CompletableFuture<T[]> findsAsync(Class<T> clazz, SelectColumn selects, Serializable... pks) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <D extends Serializable, T> List<T> findsList(Class<T> clazz, Stream<D> pks) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <D extends Serializable, T> CompletableFuture<List<T>> findsListAsync(Class<T> clazz, Stream<D> pks) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T find(Class<T> clazz, SelectColumn selects, FilterNode node) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> CompletableFuture<T> findAsync(Class<T> clazz, SelectColumn selects, FilterNode node) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Serializable findColumn(Class<T> clazz, String column, Serializable defValue, Serializable pk) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> CompletableFuture<Serializable> findColumnAsync(Class<T> clazz, String column, Serializable defValue, Serializable pk) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Serializable findColumn(Class<T> clazz, String column, Serializable defValue, FilterNode node) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> CompletableFuture<Serializable> findColumnAsync(Class<T> clazz, String column, Serializable defValue, FilterNode node) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> boolean exists(Class<T> clazz, Serializable pk) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> CompletableFuture<Boolean> existsAsync(Class<T> clazz, Serializable pk) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> boolean exists(Class<T> clazz, FilterNode node) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> CompletableFuture<Boolean> existsAsync(Class<T> clazz, FilterNode node) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, V extends Serializable> Set<V> queryColumnSet(String selectedColumn, Class<T> clazz, Flipper flipper, FilterNode node) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, V extends Serializable> CompletableFuture<Set<V>> queryColumnSetAsync(String selectedColumn, Class<T> clazz, Flipper flipper, FilterNode node) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, V extends Serializable> List<V> queryColumnList(String selectedColumn, Class<T> clazz, Flipper flipper, FilterNode node) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, V extends Serializable> CompletableFuture<List<V>> queryColumnListAsync(String selectedColumn, Class<T> clazz, Flipper flipper, FilterNode node) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, V extends Serializable> Sheet<V> queryColumnSheet(String selectedColumn, Class<T> clazz, Flipper flipper, FilterNode node) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T, V extends Serializable> CompletableFuture<Sheet<V>> queryColumnSheetAsync(String selectedColumn, Class<T> clazz, Flipper flipper, FilterNode node) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <K extends Serializable, T> Map<K, T> queryMap(Class<T> clazz, SelectColumn selects, Stream<K> keyStream) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <K extends Serializable, T> CompletableFuture<Map<K, T>> queryMapAsync(Class<T> clazz, SelectColumn selects, Stream<K> keyStream) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <K extends Serializable, T> Map<K, T> queryMap(Class<T> clazz, SelectColumn selects, FilterNode node) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <K extends Serializable, T> CompletableFuture<Map<K, T>> queryMapAsync(Class<T> clazz, SelectColumn selects, FilterNode node) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Set<T> querySet(Class<T> clazz, SelectColumn selects, Flipper flipper, FilterNode node) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> CompletableFuture<Set<T>> querySetAsync(Class<T> clazz, SelectColumn selects, Flipper flipper, FilterNode node) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> List<T> queryList(Class<T> clazz, SelectColumn selects, Flipper flipper, FilterNode node) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> CompletableFuture<List<T>> queryListAsync(Class<T> clazz, SelectColumn selects, Flipper flipper, FilterNode node) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Sheet<T> querySheet(Class<T> clazz, SelectColumn selects, Flipper flipper, FilterNode node) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> CompletableFuture<Sheet<T>> querySheetAsync(Class<T> clazz, SelectColumn selects, Flipper flipper, FilterNode node) {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
throw new UnsupportedOperationException("Not supported yet.");
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.function.*;
|
||||
import static org.redkale.source.DataResultSet.formatColumnValue;
|
||||
import org.redkale.util.Reproduce;
|
||||
import org.redkale.util.Copier;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -139,30 +139,30 @@ public interface DataSqlSource extends DataSource {
|
||||
|
||||
//----------------------------- JavaBean -----------------------------
|
||||
default int nativeUpdate(String sql, Serializable bean) {
|
||||
return nativeUpdate(sql, (Map<String, Object>) Reproduce.copy(HashMap.class, bean));
|
||||
return nativeUpdate(sql, (Map<String, Object>) Copier.copyToMap(bean, false));
|
||||
}
|
||||
|
||||
default <V> V nativeQuery(String sql, Function<DataResultSet, V> handler, Serializable bean) {
|
||||
return nativeQuery(sql, null, handler, (Map<String, Object>) Reproduce.copy(HashMap.class, bean));
|
||||
return nativeQuery(sql, null, handler, (Map<String, Object>) Copier.copyToMap(bean, false));
|
||||
}
|
||||
|
||||
default <V> V nativeQueryOne(Class<V> type, String sql, Serializable bean) {
|
||||
return nativeQueryOne(type, sql, (Map<String, Object>) Reproduce.copy(HashMap.class, bean));
|
||||
return nativeQueryOne(type, sql, (Map<String, Object>) Copier.copyToMap(bean, false));
|
||||
}
|
||||
|
||||
default <V> List<V> nativeQueryList(Class<V> type, String sql, Serializable bean) {
|
||||
return nativeQueryList(type, sql, (Map<String, Object>) Reproduce.copy(HashMap.class, bean));
|
||||
return nativeQueryList(type, sql, (Map<String, Object>) Copier.copyToMap(bean, false));
|
||||
}
|
||||
|
||||
default <K, V> Map<K, V> nativeQueryMap(Class<K> keyType, Class<V> valType, String sql, Serializable bean) {
|
||||
return nativeQueryMap(keyType, valType, sql, (Map<String, Object>) Reproduce.copy(HashMap.class, bean));
|
||||
return nativeQueryMap(keyType, valType, sql, (Map<String, Object>) Copier.copyToMap(bean, false));
|
||||
}
|
||||
|
||||
default Map<String, String> nativeQueryStrStrMap(String sql, Serializable bean) {
|
||||
return nativeQueryMap(String.class, String.class, sql, (Map<String, Object>) Reproduce.copy(HashMap.class, bean));
|
||||
return nativeQueryMap(String.class, String.class, sql, (Map<String, Object>) Copier.copyToMap(bean, false));
|
||||
}
|
||||
|
||||
default Map<Integer, String> nativeQueryIntStrMap(String sql, Serializable bean) {
|
||||
return nativeQueryMap(Integer.class, String.class, sql, (Map<String, Object>) Reproduce.copy(HashMap.class, bean));
|
||||
return nativeQueryMap(Integer.class, String.class, sql, (Map<String, Object>) Copier.copyToMap(bean, false));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,10 +62,10 @@ public final class EntityCache<T> {
|
||||
private final Attribute<T, Serializable> primary;
|
||||
|
||||
//新增时的复制器, 排除了标记为@Transient的字段
|
||||
private final Reproduce<T, T> newReproduce;
|
||||
private final Copier<T, T> newCopier;
|
||||
|
||||
//修改时的复制器, 排除了标记为@Transient或@Column(updatable=false)的字段
|
||||
private final Reproduce<T, T> chgReproduce;
|
||||
private final Copier<T, T> chgCopier;
|
||||
|
||||
//是否已经全量加载过
|
||||
private volatile boolean fullloaded;
|
||||
@@ -110,7 +110,7 @@ public final class EntityCache<T> {
|
||||
}
|
||||
}
|
||||
this.needCopy = !direct;
|
||||
this.newReproduce = Reproduce.create(type, type, (m) -> {
|
||||
this.newCopier = Copier.create(type, type, (m) -> {
|
||||
try {
|
||||
java.lang.reflect.Field field = type.getDeclaredField(m);
|
||||
return field.getAnnotation(Transient.class) == null && field.getAnnotation(javax.persistence.Transient.class) == null;
|
||||
@@ -118,7 +118,7 @@ public final class EntityCache<T> {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
this.chgReproduce = Reproduce.create(type, type, (m) -> {
|
||||
this.chgCopier = Copier.create(type, type, (m) -> {
|
||||
try {
|
||||
java.lang.reflect.Field field = type.getDeclaredField(m);
|
||||
if (field.getAnnotation(Transient.class) != null) {
|
||||
@@ -259,7 +259,7 @@ public final class EntityCache<T> {
|
||||
return null;
|
||||
}
|
||||
T rs = map.get(pk);
|
||||
return rs == null ? null : (needCopy ? newReproduce.apply(this.creator.create(), rs) : rs);
|
||||
return rs == null ? null : (needCopy ? newCopier.apply(this.creator.create(), rs) : rs);
|
||||
}
|
||||
|
||||
public T[] finds(Serializable... pks) {
|
||||
@@ -273,7 +273,7 @@ public final class EntityCache<T> {
|
||||
T[] result = arrayer.apply(ids.length);
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
T rs = map.get(ids[i]);
|
||||
result[i] = rs == null ? null : (needCopy ? newReproduce.apply(this.creator.create(), rs) : rs);
|
||||
result[i] = rs == null ? null : (needCopy ? newCopier.apply(this.creator.create(), rs) : rs);
|
||||
}
|
||||
return result;
|
||||
} else if (t == long[].class) {
|
||||
@@ -281,7 +281,7 @@ public final class EntityCache<T> {
|
||||
T[] result = arrayer.apply(ids.length);
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
T rs = map.get(ids[i]);
|
||||
result[i] = rs == null ? null : (needCopy ? newReproduce.apply(this.creator.create(), rs) : rs);
|
||||
result[i] = rs == null ? null : (needCopy ? newCopier.apply(this.creator.create(), rs) : rs);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -292,7 +292,7 @@ public final class EntityCache<T> {
|
||||
if (needCopy) {
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
T rs = array0[(Integer) pks[i]];
|
||||
result[i] = rs == null ? null : newReproduce.apply(this.creator.create(), rs);
|
||||
result[i] = rs == null ? null : newCopier.apply(this.creator.create(), rs);
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
@@ -305,7 +305,7 @@ public final class EntityCache<T> {
|
||||
T[] result = arrayer.apply(pks.length);
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
T rs = map.get(pks[i]);
|
||||
result[i] = rs == null ? null : (needCopy ? newReproduce.apply(this.creator.create(), rs) : rs);
|
||||
result[i] = rs == null ? null : (needCopy ? newCopier.apply(this.creator.create(), rs) : rs);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -319,7 +319,7 @@ public final class EntityCache<T> {
|
||||
return null;
|
||||
}
|
||||
if (selects == null) {
|
||||
return (needCopy ? newReproduce.apply(this.creator.create(), rs) : rs);
|
||||
return (needCopy ? newCopier.apply(this.creator.create(), rs) : rs);
|
||||
}
|
||||
T t = this.creator.create();
|
||||
for (Attribute attr : this.info.attributes) {
|
||||
@@ -358,7 +358,7 @@ public final class EntityCache<T> {
|
||||
}
|
||||
if (selects == null) {
|
||||
if (needCopy) {
|
||||
rs = newReproduce.apply(ctr.create(), rs);
|
||||
rs = newCopier.apply(ctr.create(), rs);
|
||||
}
|
||||
} else {
|
||||
T t = ctr.create();
|
||||
@@ -385,7 +385,7 @@ public final class EntityCache<T> {
|
||||
return null;
|
||||
}
|
||||
if (selects == null) {
|
||||
return (needCopy ? newReproduce.apply(this.creator.create(), opt.get()) : opt.get());
|
||||
return (needCopy ? newCopier.apply(this.creator.create(), opt.get()) : opt.get());
|
||||
}
|
||||
T rs = opt.get();
|
||||
T t = this.creator.create();
|
||||
@@ -765,7 +765,7 @@ public final class EntityCache<T> {
|
||||
}
|
||||
final List<T> rs = new ArrayList<>();
|
||||
if (selects == null) {
|
||||
Consumer<? super T> action = x -> rs.add(needCopy ? newReproduce.apply(creator.create(), x) : x);
|
||||
Consumer<? super T> action = x -> rs.add(needCopy ? newCopier.apply(creator.create(), x) : x);
|
||||
if (comparator != null) {
|
||||
stream.forEachOrdered(action);
|
||||
} else {
|
||||
@@ -801,7 +801,7 @@ public final class EntityCache<T> {
|
||||
if (entity == null) {
|
||||
return 0;
|
||||
}
|
||||
final T rs = newReproduce.apply(this.creator.create(), entity); //确保同一主键值的map与list中的对象必须共用。
|
||||
final T rs = newCopier.apply(this.creator.create(), entity); //确保同一主键值的map与list中的对象必须共用。
|
||||
T old = this.map.putIfAbsent(this.primary.get(rs), rs);
|
||||
if (old == null) {
|
||||
this.list.add(rs);
|
||||
@@ -874,7 +874,7 @@ public final class EntityCache<T> {
|
||||
}
|
||||
tableLock.lock(); //表锁, 可优化成行锁
|
||||
try {
|
||||
this.chgReproduce.apply(rs, entity);
|
||||
this.chgCopier.apply(rs, entity);
|
||||
} finally {
|
||||
tableLock.unlock();
|
||||
}
|
||||
|
||||
718
src/main/java/org/redkale/util/Copier.java
Normal file
718
src/main/java/org/redkale/util/Copier.java
Normal file
@@ -0,0 +1,718 @@
|
||||
/*
|
||||
*
|
||||
*/
|
||||
package org.redkale.util;
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.function.*;
|
||||
import static org.redkale.asm.ClassWriter.COMPUTE_FRAMES;
|
||||
import org.redkale.asm.*;
|
||||
import static org.redkale.asm.Opcodes.*;
|
||||
import org.redkale.asm.Type;
|
||||
|
||||
/**
|
||||
* JavaBean类对象的拷贝,相同的字段名会被拷贝 <br>
|
||||
*
|
||||
* <p>
|
||||
* 详情见: https://redkale.org
|
||||
*
|
||||
* @author zhangjx
|
||||
* @param <D> 目标对象的数据类型
|
||||
* @param <S> 源对象的数据类型
|
||||
*/
|
||||
public interface Copier<S, D> extends BiFunction<S, D, D> {
|
||||
|
||||
/**
|
||||
* 将源对象字段复制到目标对象
|
||||
*
|
||||
* @param dest 目标对象
|
||||
* @param src 源对象
|
||||
*
|
||||
* @return 目标对象
|
||||
*/
|
||||
@Override
|
||||
public D apply(S src, D dest);
|
||||
|
||||
/**
|
||||
* 将源对象字段复制到目标对象
|
||||
*
|
||||
* @param <D> 目标类泛型
|
||||
* @param <S> 源类泛型
|
||||
* @param dest 目标对象
|
||||
* @param src 源对象
|
||||
*
|
||||
* @return 目标对象
|
||||
*/
|
||||
public static <S, D> D copy(final S src, final D dest) {
|
||||
if (src == null || dest == null) {
|
||||
return null;
|
||||
}
|
||||
Class<D> destClass = (Class<D>) dest.getClass();
|
||||
Creator<D> creator = Creator.load(destClass);
|
||||
return load((Class<S>) src.getClass(), destClass).apply(src, creator.create());
|
||||
}
|
||||
|
||||
/**
|
||||
* 将源对象字段复制到目标对象
|
||||
*
|
||||
* @param <D> 目标类泛型
|
||||
* @param <S> 源类泛型
|
||||
* @param destClass 目标类名
|
||||
* @param src 源对象
|
||||
*
|
||||
* @return 目标对象
|
||||
*/
|
||||
public static <S, D> D copy(final S src, final Class<D> destClass) {
|
||||
if (src == null) {
|
||||
return null;
|
||||
}
|
||||
Creator<D> creator = Creator.load(destClass);
|
||||
return load((Class<S>) src.getClass(), destClass).apply(src, creator.create());
|
||||
}
|
||||
|
||||
/**
|
||||
* 将源对象字段复制到目标对象
|
||||
*
|
||||
* @param <S> 源类泛型
|
||||
* @param src 源对象
|
||||
* @param allowMapNullVal 是否允许复制value为null的键值对
|
||||
*
|
||||
* @return 目标对象
|
||||
*/
|
||||
public static <S> Map copyToMap(final S src, final boolean allowMapNullVal) {
|
||||
if (src == null) {
|
||||
return null;
|
||||
}
|
||||
HashMap dest = new HashMap();
|
||||
return load((Class<S>) src.getClass(), HashMap.class, allowMapNullVal).apply(src, dest);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建源类到目标类的复制器并缓存
|
||||
*
|
||||
* @param <D> 目标类泛型
|
||||
* @param <S> 源类泛型
|
||||
* @param destClass 目标类名
|
||||
* @param srcClass 源类名
|
||||
*
|
||||
* @return 复制器
|
||||
*/
|
||||
public static <S, D> Copier<S, D> load(final Class<S> srcClass, final Class<D> destClass) {
|
||||
if (destClass == srcClass) {
|
||||
return CopierInner.copierOneCaches
|
||||
.computeIfAbsent(srcClass, v -> create(srcClass, destClass));
|
||||
} else {
|
||||
return CopierInner.copierTwoCaches
|
||||
.computeIfAbsent(srcClass, t -> new ConcurrentHashMap<>())
|
||||
.computeIfAbsent(destClass, v -> create(srcClass, destClass));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建源类到目标类的复制器并缓存
|
||||
*
|
||||
* @param <D> 目标类泛型
|
||||
* @param <S> 源类泛型
|
||||
* @param destClass 目标类名
|
||||
* @param srcClass 源类名
|
||||
* @param allowMapNullVal 是否允许复制value为null的键值对
|
||||
*
|
||||
* @return 复制器
|
||||
*/
|
||||
public static <S, D extends Map> Copier<S, D> load(final Class<S> srcClass, final Class<D> destClass, final boolean allowMapNullVal) {
|
||||
if (destClass == srcClass) {
|
||||
return CopierInner.copierOneCaches
|
||||
.computeIfAbsent(srcClass, v -> create(srcClass, destClass, allowMapNullVal, (BiPredicate) null, (Map<String, String>) null));
|
||||
} else {
|
||||
return CopierInner.copierTwoCaches
|
||||
.computeIfAbsent(srcClass, t -> new ConcurrentHashMap<>())
|
||||
.computeIfAbsent(destClass, v -> create(srcClass, destClass, allowMapNullVal, (BiPredicate) null, (Map<String, String>) null));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建源类到目标类的复制器
|
||||
*
|
||||
* @param <D> 目标类泛型
|
||||
* @param <S> 源类泛型
|
||||
* @param destClass 目标类名
|
||||
* @param srcClass 源类名
|
||||
*
|
||||
* @return 复制器
|
||||
*/
|
||||
public static <S, D> Copier<S, D> create(final Class<S> srcClass, final Class<D> destClass) {
|
||||
return create(srcClass, destClass, (BiPredicate) null, (Map<String, String>) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建源类到目标类的复制器
|
||||
*
|
||||
* @param <D> 目标类泛型
|
||||
* @param <S> 源类泛型
|
||||
* @param destClass 目标类名
|
||||
* @param srcClass 源类名
|
||||
* @param names 源字段名与目标字段名的映射关系
|
||||
*
|
||||
* @return 复制器
|
||||
*/
|
||||
public static <S, D> Copier<S, D> create(final Class<S> srcClass, final Class<D> destClass, final Map<String, String> names) {
|
||||
return create(srcClass, destClass, (BiPredicate) null, names);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建源类到目标类的复制器
|
||||
*
|
||||
* @param <D> 目标类泛型
|
||||
* @param <S> 源类泛型
|
||||
* @param destClass 目标类名
|
||||
* @param srcClass 源类名
|
||||
* @param srcColumnPredicate 需复制的字段名判断期
|
||||
*
|
||||
* @return 复制器
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <S, D> Copier<S, D> create(final Class<S> srcClass, final Class<D> destClass, final Predicate<String> srcColumnPredicate) {
|
||||
return create(srcClass, destClass, (sc, m) -> srcColumnPredicate.test(m), (Map<String, String>) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建源类到目标类的复制器
|
||||
*
|
||||
* @param <D> 目标类泛型
|
||||
* @param <S> 源类泛型
|
||||
* @param destClass 目标类名
|
||||
* @param srcClass 源类名
|
||||
* @param srcColumnPredicate 需复制的字段名判断期
|
||||
* @param names 源字段名与目标字段名的映射关系
|
||||
*
|
||||
* @return 复制器
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <S, D> Copier<S, D> create(final Class<S> srcClass, final Class<D> destClass, final Predicate<String> srcColumnPredicate, final Map<String, String> names) {
|
||||
return create(srcClass, destClass, (sc, m) -> srcColumnPredicate.test(m), names);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建源类到目标类的复制器
|
||||
*
|
||||
* @param <D> 目标类泛型
|
||||
* @param <S> 源类泛型
|
||||
* @param destClass 目标类名
|
||||
* @param srcClass 源类名
|
||||
* @param srcColumnPredicate 需复制的字段名判断期
|
||||
*
|
||||
* @return 复制器
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <S, D> Copier<S, D> create(final Class<S> srcClass, final Class<D> destClass, final BiPredicate<java.lang.reflect.AccessibleObject, String> srcColumnPredicate) {
|
||||
return create(srcClass, destClass, srcColumnPredicate, (Map<String, String>) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建源类到目标类的复制器
|
||||
*
|
||||
* @param <D> 目标类泛型
|
||||
* @param <S> 源类泛型
|
||||
* @param destClass 目标类名
|
||||
* @param srcClass 源类名
|
||||
* @param srcColumnPredicate 需复制的字段名判断期
|
||||
* @param names 源字段名与目标字段名的映射关系
|
||||
*
|
||||
* @return 复制器
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <S, D> Copier<S, D> create(final Class<S> srcClass, final Class<D> destClass, final BiPredicate<java.lang.reflect.AccessibleObject, String> srcColumnPredicate, final Map<String, String> names) {
|
||||
return create(srcClass, destClass, false, srcColumnPredicate, names);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建源类到目标类的复制器
|
||||
*
|
||||
* @param <D> 目标类泛型
|
||||
* @param <S> 源类泛型
|
||||
* @param destClass 目标类名
|
||||
* @param srcClass 源类名
|
||||
* @param allowMapNullVal 目标类是Map子类时是否允许复制value为null的键值对
|
||||
* @param srcColumnPredicate 需复制的字段名判断期
|
||||
* @param names 源字段名与目标字段名的映射关系
|
||||
*
|
||||
* @return 复制器
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <S, D> Copier<S, D> create(final Class<S> srcClass, final Class<D> destClass, final boolean allowMapNullVal, final BiPredicate<java.lang.reflect.AccessibleObject, String> srcColumnPredicate, final Map<String, String> names) {
|
||||
final boolean allowMapNull = allowMapNullVal && !ConcurrentHashMap.class.isAssignableFrom(destClass);
|
||||
if (Map.class.isAssignableFrom(destClass) && Map.class.isAssignableFrom(srcClass)) {
|
||||
final Map names0 = names;
|
||||
if (srcColumnPredicate != null) {
|
||||
if (names != null) {
|
||||
return (S src, D dest) -> {
|
||||
Map d = (Map) dest;
|
||||
((Map) src).forEach((k, v) -> {
|
||||
if (srcColumnPredicate.test(null, k.toString()) && (allowMapNull || v != null)) {
|
||||
d.put(names0.getOrDefault(k, k), v);
|
||||
}
|
||||
});
|
||||
return dest;
|
||||
};
|
||||
} else {
|
||||
return (S src, D dest) -> {
|
||||
Map d = (Map) dest;
|
||||
((Map) src).forEach((k, v) -> {
|
||||
if (srcColumnPredicate.test(null, k.toString()) && (allowMapNull || v != null)) {
|
||||
d.put(k, v);
|
||||
}
|
||||
});
|
||||
return dest;
|
||||
};
|
||||
}
|
||||
} else if (names != null) {
|
||||
return (S src, D dest) -> {
|
||||
Map d = (Map) dest;
|
||||
((Map) src).forEach((k, v) -> {
|
||||
if (allowMapNull || v != null) {
|
||||
d.put(names0.getOrDefault(k, k), v);
|
||||
}
|
||||
});
|
||||
return dest;
|
||||
};
|
||||
}
|
||||
return new Copier<S, D>() {
|
||||
@Override
|
||||
public D apply(S src, D dest) {
|
||||
if (allowMapNull) {
|
||||
((Map) dest).putAll((Map) src);
|
||||
} else {
|
||||
Map d = (Map) dest;
|
||||
((Map) src).forEach((k, v) -> {
|
||||
if (v != null) {
|
||||
d.put(k, v);
|
||||
}
|
||||
});
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
};
|
||||
}
|
||||
// ------------------------------------------------------------------------------
|
||||
final boolean destIsMap = Map.class.isAssignableFrom(destClass);
|
||||
final boolean srcIsMap = Map.class.isAssignableFrom(srcClass);
|
||||
final String supDynName = Copier.class.getName().replace('.', '/');
|
||||
final String destClassName = destClass.getName().replace('.', '/');
|
||||
final String srcClassName = srcClass.getName().replace('.', '/');
|
||||
final String destDesc = Type.getDescriptor(destClass);
|
||||
final String srcDesc = Type.getDescriptor(srcClass);
|
||||
final ClassLoader loader = Thread.currentThread().getContextClassLoader();
|
||||
final String utilClassName = Utility.class.getName().replace('.', '/');
|
||||
final String newDynName = "org/redkaledyn/copier/_Dyn" + Copier.class.getSimpleName()
|
||||
+ "__" + srcClass.getName().replace('.', '_').replace('$', '_')
|
||||
+ "__" + destClass.getName().replace('.', '_').replace('$', '_');
|
||||
try {
|
||||
Class clz = RedkaleClassLoader.findDynClass(newDynName.replace('/', '.'));
|
||||
return (Copier) (clz == null ? loader.loadClass(newDynName.replace('/', '.')) : clz).getDeclaredConstructor().newInstance();
|
||||
} catch (Throwable ex) {
|
||||
}
|
||||
final Predicate<Class<?>> throwPredicate = e -> !RuntimeException.class.isAssignableFrom(e);
|
||||
// ------------------------------------------------------------------------------
|
||||
ClassWriter cw = new ClassWriter(COMPUTE_FRAMES);
|
||||
FieldVisitor fv;
|
||||
MethodVisitor mv;
|
||||
AnnotationVisitor av0;
|
||||
|
||||
cw.visit(V11, ACC_PUBLIC + ACC_FINAL + ACC_SUPER, newDynName, "Ljava/lang/Object;L" + supDynName + "<" + srcDesc + destDesc + ">;", "java/lang/Object", new String[]{supDynName});
|
||||
|
||||
{ // 构造函数
|
||||
mv = (cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null));
|
||||
//mv.setDebug(true);
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V", false);
|
||||
mv.visitInsn(RETURN);
|
||||
mv.visitMaxs(1, 1);
|
||||
mv.visitEnd();
|
||||
}
|
||||
if (srcIsMap) { //destClass不是Map
|
||||
{
|
||||
mv = (cw.visitMethod(ACC_PUBLIC, "apply", "(" + srcDesc + destDesc + ")" + destDesc, null, null));
|
||||
//mv.setDebug(true);
|
||||
mv.visitVarInsn(ALOAD, 1);
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
mv.visitInvokeDynamicInsn("accept",
|
||||
"(" + destDesc + ")Ljava/util/function/BiConsumer;",
|
||||
new Handle(Opcodes.H_INVOKESTATIC, "java/lang/invoke/LambdaMetafactory", "metafactory", "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodType;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)Ljava/lang/invoke/CallSite;", false),
|
||||
new Object[]{Type.getType("(Ljava/lang/Object;Ljava/lang/Object;)V"), new Handle(Opcodes.H_INVOKESTATIC, newDynName, "lambda$0", "(" + destDesc + "Ljava/lang/Object;Ljava/lang/Object;)V", false), Type.getType("(Ljava/lang/Object;Ljava/lang/Object;)V")});
|
||||
mv.visitMethodInsn(srcClass.isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL, srcClassName, "forEach", "(Ljava/util/function/BiConsumer;)V", srcClass.isInterface());
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
mv.visitInsn(ARETURN);
|
||||
mv.visitMaxs(2, 3);
|
||||
mv.visitEnd();
|
||||
}
|
||||
{
|
||||
final Map<String, AccessibleObject> elements = new LinkedHashMap<>();
|
||||
for (java.lang.reflect.Field field : destClass.getFields()) {
|
||||
if (Modifier.isStatic(field.getModifiers())) {
|
||||
continue;
|
||||
}
|
||||
if (Modifier.isFinal(field.getModifiers())) {
|
||||
continue;
|
||||
}
|
||||
if (!Modifier.isPublic(field.getModifiers())) {
|
||||
continue;
|
||||
}
|
||||
final String sfname = field.getName();
|
||||
if (srcColumnPredicate != null && !srcColumnPredicate.test(field, sfname)) {
|
||||
continue;
|
||||
}
|
||||
final String dfname = names == null ? sfname : names.getOrDefault(sfname, sfname);
|
||||
elements.put(dfname, field);
|
||||
}
|
||||
|
||||
for (java.lang.reflect.Method setter : destClass.getMethods()) {
|
||||
if (Modifier.isStatic(setter.getModifiers())) {
|
||||
continue;
|
||||
}
|
||||
if (setter.getParameterTypes().length != 1) {
|
||||
continue;
|
||||
}
|
||||
if (Utility.contains(setter.getExceptionTypes(), throwPredicate)) {
|
||||
continue; //setter方法带有非RuntimeException异常
|
||||
}
|
||||
if (!setter.getName().startsWith("set")) {
|
||||
continue;
|
||||
}
|
||||
String sfname = Utility.readFieldName(setter.getName());
|
||||
if (sfname.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
if (srcColumnPredicate != null && !srcColumnPredicate.test(setter, sfname)) {
|
||||
continue;
|
||||
}
|
||||
final String dfname = names == null ? sfname : names.getOrDefault(sfname, sfname);
|
||||
elements.put(dfname, setter);
|
||||
}
|
||||
|
||||
mv = cw.visitMethod(ACC_PRIVATE + ACC_STATIC + ACC_SYNTHETIC, "lambda$0", "(" + destDesc + "Ljava/lang/Object;Ljava/lang/Object;)V", null, null);
|
||||
Label goLabel = new Label();
|
||||
int i = 0;
|
||||
for (Map.Entry<String, AccessibleObject> en : elements.entrySet()) {
|
||||
final int index = ++i;
|
||||
final java.lang.reflect.Type fieldType = en.getValue() instanceof Field
|
||||
? ((Field) en.getValue()).getGenericType()
|
||||
: ((Method) en.getValue()).getGenericParameterTypes()[0];
|
||||
final Class fieldClass = en.getValue() instanceof Field
|
||||
? ((Field) en.getValue()).getType()
|
||||
: ((Method) en.getValue()).getParameterTypes()[0];
|
||||
final boolean primitive = fieldClass.isPrimitive();
|
||||
|
||||
mv.visitLdcInsn(en.getKey());
|
||||
mv.visitVarInsn(ALOAD, 1);
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z", false);
|
||||
Label ifeq = index == elements.size() ? goLabel : new Label();
|
||||
mv.visitJumpInsn(IFEQ, ifeq);
|
||||
if (primitive) {
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
mv.visitJumpInsn(IFNULL, ifeq);
|
||||
}
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
|
||||
if (fieldClass == boolean.class) {
|
||||
mv.visitFieldInsn(GETSTATIC, "java/lang/Boolean", "TYPE", "Ljava/lang/Class;");
|
||||
} else if (fieldClass == byte.class) {
|
||||
mv.visitFieldInsn(GETSTATIC, "java/lang/Byte", "TYPE", "Ljava/lang/Class;");
|
||||
} else if (fieldClass == char.class) {
|
||||
mv.visitFieldInsn(GETSTATIC, "java/lang/Character", "TYPE", "Ljava/lang/Class;");
|
||||
} else if (fieldClass == short.class) {
|
||||
mv.visitFieldInsn(GETSTATIC, "java/lang/Short", "TYPE", "Ljava/lang/Class;");
|
||||
} else if (fieldClass == int.class) {
|
||||
mv.visitFieldInsn(GETSTATIC, "java/lang/Integer", "TYPE", "Ljava/lang/Class;");
|
||||
} else if (fieldClass == float.class) {
|
||||
mv.visitFieldInsn(GETSTATIC, "java/lang/Float", "TYPE", "Ljava/lang/Class;");
|
||||
} else if (fieldClass == long.class) {
|
||||
mv.visitFieldInsn(GETSTATIC, "java/lang/Long", "TYPE", "Ljava/lang/Class;");
|
||||
} else if (fieldClass == double.class) {
|
||||
mv.visitFieldInsn(GETSTATIC, "java/lang/Double", "TYPE", "Ljava/lang/Class;");
|
||||
} else {
|
||||
mv.visitLdcInsn(Type.getType(Type.getDescriptor(fieldClass)));
|
||||
}
|
||||
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
mv.visitMethodInsn(INVOKESTATIC, utilClassName, "convertValue", "(Ljava/lang/reflect/Type;Ljava/lang/Object;)Ljava/lang/Object;", false);
|
||||
if (fieldClass == boolean.class) {
|
||||
mv.visitTypeInsn(CHECKCAST, "java/lang/Boolean");
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Boolean", "booleanValue", "()Z", false);
|
||||
} else if (fieldClass == byte.class) {
|
||||
mv.visitTypeInsn(CHECKCAST, "java/lang/Byte");
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Byte", "byteValue", "()B", false);
|
||||
} else if (fieldClass == short.class) {
|
||||
mv.visitTypeInsn(CHECKCAST, "java/lang/Short");
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Short", "shortValue", "()S", false);
|
||||
} else if (fieldClass == char.class) {
|
||||
mv.visitTypeInsn(CHECKCAST, "java/lang/Character");
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Character", "charValue", "()C", false);
|
||||
} else if (fieldClass == int.class) {
|
||||
mv.visitTypeInsn(CHECKCAST, "java/lang/Integer");
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Integer", "intValue", "()I", false);
|
||||
} else if (fieldClass == float.class) {
|
||||
mv.visitTypeInsn(CHECKCAST, "java/lang/Float");
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Float", "floatValue", "()F", false);
|
||||
} else if (fieldClass == long.class) {
|
||||
mv.visitTypeInsn(CHECKCAST, "java/lang/Long");
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Long", "longValue", "()J", false);
|
||||
} else if (fieldClass == double.class) {
|
||||
mv.visitTypeInsn(CHECKCAST, "java/lang/Double");
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/Double", "doubleValue", "()D", false);
|
||||
} else {
|
||||
mv.visitTypeInsn(CHECKCAST, fieldClass.getName().replace('.', '/'));
|
||||
}
|
||||
|
||||
if (en.getValue() instanceof Field) {
|
||||
mv.visitFieldInsn(PUTFIELD, destClassName, en.getKey(), Type.getDescriptor(fieldClass));
|
||||
} else {
|
||||
Method setter = (Method) en.getValue();
|
||||
mv.visitMethodInsn(destClass.isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL, destClassName, setter.getName(), Type.getMethodDescriptor(setter), destClass.isInterface());
|
||||
}
|
||||
if (index == elements.size()) {
|
||||
mv.visitLabel(goLabel);
|
||||
} else {
|
||||
mv.visitJumpInsn(GOTO, goLabel);
|
||||
mv.visitLabel(ifeq);
|
||||
}
|
||||
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
|
||||
}
|
||||
|
||||
mv.visitInsn(RETURN);
|
||||
mv.visitMaxs(3, 3);
|
||||
mv.visitEnd();
|
||||
}
|
||||
} else {
|
||||
mv = (cw.visitMethod(ACC_PUBLIC, "apply", "(" + srcDesc + destDesc + ")" + destDesc, null, null));
|
||||
//mv.setDebug(true);
|
||||
|
||||
for (java.lang.reflect.Field field : srcClass.getFields()) {
|
||||
if (Modifier.isStatic(field.getModifiers())) {
|
||||
continue;
|
||||
}
|
||||
if (Modifier.isFinal(field.getModifiers())) {
|
||||
continue;
|
||||
}
|
||||
if (!Modifier.isPublic(field.getModifiers())) {
|
||||
continue;
|
||||
}
|
||||
final String sfname = field.getName();
|
||||
if (srcColumnPredicate != null && !srcColumnPredicate.test(field, sfname)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final String dfname = names == null ? sfname : names.getOrDefault(sfname, sfname);
|
||||
if (destIsMap) {
|
||||
Class st = field.getType();
|
||||
String td = Type.getDescriptor(st);
|
||||
if (allowMapNull || st.isPrimitive()) {
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
mv.visitLdcInsn(dfname);
|
||||
mv.visitVarInsn(ALOAD, 1);
|
||||
mv.visitFieldInsn(GETFIELD, srcClassName, sfname, td);
|
||||
if (st == boolean.class) {
|
||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false);
|
||||
} else if (st == byte.class) {
|
||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false);
|
||||
} else if (st == short.class) {
|
||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false);
|
||||
} else if (st == char.class) {
|
||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false);
|
||||
} else if (st == int.class) {
|
||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
|
||||
} else if (st == float.class) {
|
||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false);
|
||||
} else if (st == long.class) {
|
||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false);
|
||||
} else if (st == double.class) {
|
||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false);
|
||||
}
|
||||
mv.visitMethodInsn(destClass.isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL, destClassName, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", destClass.isInterface());
|
||||
mv.visitInsn(POP);
|
||||
} else {
|
||||
mv.visitVarInsn(ALOAD, 1);
|
||||
mv.visitFieldInsn(GETFIELD, srcClassName, sfname, td);
|
||||
mv.visitVarInsn(ASTORE, 3);
|
||||
mv.visitVarInsn(ALOAD, 3);
|
||||
Label ifLabel = new Label();
|
||||
mv.visitJumpInsn(IFNULL, ifLabel);
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
mv.visitLdcInsn(dfname);
|
||||
mv.visitVarInsn(ALOAD, 3);
|
||||
mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Map", "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", true);
|
||||
mv.visitInsn(POP);
|
||||
mv.visitLabel(ifLabel);
|
||||
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
|
||||
}
|
||||
} else {
|
||||
java.lang.reflect.Method setter = null;
|
||||
try {
|
||||
if (!field.getType().equals(destClass.getField(dfname).getType())) {
|
||||
continue;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
try {
|
||||
char[] cs = dfname.toCharArray();
|
||||
cs[0] = Character.toUpperCase(cs[0]);
|
||||
String dfname2 = new String(cs);
|
||||
setter = destClass.getMethod("set" + dfname2, field.getType());
|
||||
} catch (Exception e2) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
mv.visitVarInsn(ALOAD, 1);
|
||||
String td = Type.getDescriptor(field.getType());
|
||||
mv.visitFieldInsn(GETFIELD, srcClassName, sfname, td);
|
||||
if (setter == null) {
|
||||
mv.visitFieldInsn(PUTFIELD, destClassName, dfname, td);
|
||||
} else {
|
||||
mv.visitMethodInsn(destClass.isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL, destClassName, setter.getName(), Type.getMethodDescriptor(setter), destClass.isInterface());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (java.lang.reflect.Method getter : srcClass.getMethods()) {
|
||||
if (Modifier.isStatic(getter.getModifiers())) {
|
||||
continue;
|
||||
}
|
||||
if (getter.getParameterTypes().length > 0) {
|
||||
continue;
|
||||
}
|
||||
if ("getClass".equals(getter.getName())) {
|
||||
continue;
|
||||
}
|
||||
if (Utility.contains(getter.getExceptionTypes(), throwPredicate)) {
|
||||
continue; //setter方法带有非RuntimeException异常
|
||||
}
|
||||
if (!getter.getName().startsWith("get") && !getter.getName().startsWith("is")) {
|
||||
continue;
|
||||
}
|
||||
final String sfname = Utility.readFieldName(getter.getName());
|
||||
if (sfname.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
if (srcColumnPredicate != null && !srcColumnPredicate.test(getter, sfname)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
final String dfname = names == null ? sfname : names.getOrDefault(sfname, sfname);
|
||||
if (destIsMap) {
|
||||
Class st = getter.getReturnType();
|
||||
if (allowMapNull || st.isPrimitive()) {
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
mv.visitLdcInsn(dfname);
|
||||
mv.visitVarInsn(ALOAD, 1);
|
||||
mv.visitMethodInsn(srcClass.isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL, srcClassName, getter.getName(), Type.getMethodDescriptor(getter), srcClass.isInterface());
|
||||
if (st == boolean.class) {
|
||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;", false);
|
||||
} else if (st == byte.class) {
|
||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;", false);
|
||||
} else if (st == short.class) {
|
||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;", false);
|
||||
} else if (st == char.class) {
|
||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;", false);
|
||||
} else if (st == int.class) {
|
||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;", false);
|
||||
} else if (st == float.class) {
|
||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;", false);
|
||||
} else if (st == long.class) {
|
||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;", false);
|
||||
} else if (st == double.class) {
|
||||
mv.visitMethodInsn(INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;", false);
|
||||
}
|
||||
mv.visitMethodInsn(destClass.isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL, destClassName, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", destClass.isInterface());
|
||||
mv.visitInsn(POP);
|
||||
} else {
|
||||
mv.visitVarInsn(ALOAD, 1);
|
||||
mv.visitMethodInsn(srcClass.isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL, srcClassName, getter.getName(), Type.getMethodDescriptor(getter), srcClass.isInterface());
|
||||
mv.visitVarInsn(ASTORE, 3);
|
||||
mv.visitVarInsn(ALOAD, 3);
|
||||
Label ifLabel = new Label();
|
||||
mv.visitJumpInsn(IFNULL, ifLabel);
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
mv.visitLdcInsn(dfname);
|
||||
mv.visitVarInsn(ALOAD, 3);
|
||||
mv.visitMethodInsn(destClass.isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL, destClassName, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", destClass.isInterface());
|
||||
mv.visitInsn(POP);
|
||||
mv.visitLabel(ifLabel);
|
||||
mv.visitLineNumber(47, ifLabel);
|
||||
mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
|
||||
}
|
||||
} else {
|
||||
java.lang.reflect.Method setter = null;
|
||||
java.lang.reflect.Field srcField = null;
|
||||
char[] cs = dfname.toCharArray();
|
||||
cs[0] = Character.toUpperCase(cs[0]);
|
||||
String dfname2 = new String(cs);
|
||||
try {
|
||||
setter = destClass.getMethod("set" + dfname2, getter.getReturnType());
|
||||
if (Utility.contains(setter.getExceptionTypes(), throwPredicate)) {
|
||||
continue; //setter方法带有非RuntimeException异常
|
||||
}
|
||||
} catch (Exception e) {
|
||||
try {
|
||||
srcField = destClass.getField(dfname);
|
||||
if (!getter.getReturnType().equals(srcField.getType())) {
|
||||
continue;
|
||||
}
|
||||
} catch (Exception e2) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
mv.visitVarInsn(ALOAD, 1);
|
||||
mv.visitMethodInsn(srcClass.isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL, srcClassName, getter.getName(), Type.getMethodDescriptor(getter), srcClass.isInterface());
|
||||
if (srcField == null) {
|
||||
mv.visitMethodInsn(destClass.isInterface() ? INVOKEINTERFACE : INVOKEVIRTUAL, destClassName, setter.getName(), Type.getMethodDescriptor(setter), destClass.isInterface());
|
||||
} else {
|
||||
mv.visitFieldInsn(PUTFIELD, destClassName, dfname, Type.getDescriptor(getter.getReturnType()));
|
||||
}
|
||||
}
|
||||
}
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
mv.visitInsn(ARETURN);
|
||||
mv.visitMaxs(3, 3);
|
||||
mv.visitEnd();
|
||||
}
|
||||
{
|
||||
mv = (cw.visitMethod(ACC_PUBLIC + ACC_BRIDGE + ACC_SYNTHETIC, "apply", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;", null, null));
|
||||
//mv.setDebug(true);
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitVarInsn(ALOAD, 1);
|
||||
mv.visitTypeInsn(CHECKCAST, srcClassName);
|
||||
mv.visitVarInsn(ALOAD, 2);
|
||||
mv.visitTypeInsn(CHECKCAST, destClassName);
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, newDynName, "apply", "(" + srcDesc + destDesc + ")" + destDesc, false);
|
||||
mv.visitInsn(ARETURN);
|
||||
mv.visitMaxs(3, 3);
|
||||
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);
|
||||
RedkaleClassLoader.putDynClass(newDynName.replace('/', '.'), bytes, newClazz);
|
||||
RedkaleClassLoader.putReflectionDeclaredConstructors(newClazz, newDynName.replace('/', '.'));
|
||||
try {
|
||||
return (Copier) newClazz.getDeclaredConstructor().newInstance();
|
||||
} catch (Exception ex) {
|
||||
throw new RedkaleException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
static class CopierInner {
|
||||
|
||||
static final ConcurrentHashMap<Class, Copier> copierOneCaches = new ConcurrentHashMap();
|
||||
|
||||
static final ConcurrentHashMap<Class, ConcurrentHashMap<Class, Copier>> copierTwoCaches = new ConcurrentHashMap();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -966,7 +966,12 @@ public final class ResourceFactory {
|
||||
}
|
||||
}
|
||||
if (rs == null && re == null && autoRegNull && rcname.indexOf(Resource.PARENT_NAME) < 0) {
|
||||
register(rcname, gencType, null); //自动注入null的值
|
||||
if (rcname.startsWith("${")) {
|
||||
String sub = rcname.substring(rcname.lastIndexOf("${") + 2, rcname.lastIndexOf('}'));
|
||||
register(sub, gencType, null); //自动注入null的值
|
||||
} else {
|
||||
register(rcname, gencType, null); //自动注入null的值
|
||||
}
|
||||
re = findEntry(rcname, gencType);
|
||||
}
|
||||
if (re != null) {
|
||||
|
||||
@@ -4,16 +4,16 @@
|
||||
package org.redkale.test.util;
|
||||
|
||||
import java.util.Map;
|
||||
import org.redkale.util.Reproduce;
|
||||
import org.redkale.util.Copier;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class ReproduceBeanMap implements Reproduce<Map<String, Object>, TestInterface> {
|
||||
public class CopierBeanMap implements Copier<TestInterface, Map<String, Object>> {
|
||||
|
||||
@Override
|
||||
public Map apply(Map<String, Object> dest, TestInterface src) {
|
||||
public Map apply(TestInterface src, Map<String, Object> dest) {
|
||||
Object v;
|
||||
dest.put("id", src.getId());
|
||||
|
||||
@@ -24,7 +24,7 @@ public class ReproduceBeanMap implements Reproduce<Map<String, Object>, TestInte
|
||||
return dest;
|
||||
}
|
||||
|
||||
public Map run(Map<String, Object> dest, TestBean src) {
|
||||
public Map run(TestBean src, Map<String, Object> dest) {
|
||||
Object v;
|
||||
|
||||
v = src.getName();
|
||||
@@ -9,10 +9,10 @@ import org.redkale.util.*;
|
||||
/**
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class ReproduceMapBean implements Reproduce<TestBean, HashMap> {
|
||||
public class CopierMapBean implements Copier<HashMap, TestBean> {
|
||||
|
||||
@Override
|
||||
public TestBean apply(TestBean dest, HashMap src) {
|
||||
public TestBean apply(HashMap src, TestBean dest) {
|
||||
src.forEach((k, v) -> {
|
||||
if ("id".equals(k) && v != null) {
|
||||
dest.setId(Utility.convertValue(int.class, v));
|
||||
@@ -13,10 +13,10 @@ import org.redkale.util.*;
|
||||
*
|
||||
* @author zhangjx
|
||||
*/
|
||||
public class ReproduceTest {
|
||||
public class CopierTest {
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
ReproduceTest test = new ReproduceTest();
|
||||
CopierTest test = new CopierTest();
|
||||
test.run1();
|
||||
test.run2();
|
||||
test.run3();
|
||||
@@ -33,9 +33,9 @@ public class ReproduceTest {
|
||||
bean.time = 55555L;
|
||||
bean.setName("haha");
|
||||
bean.setMap(Utility.ofMap("aa", "bbb"));
|
||||
Map map = new TreeMap(Reproduce.copy(Map.class, bean));
|
||||
Map map = new TreeMap(Copier.copy(bean, Map.class));
|
||||
System.out.println(JsonConvert.root().convertTo(map));
|
||||
TreeMap rs = Reproduce.copy(TreeMap.class, bean);
|
||||
TreeMap rs = Copier.copy(bean, TreeMap.class);
|
||||
Assertions.assertEquals(bean.toString(), JsonConvert.root().convertTo(rs));
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ public class ReproduceTest {
|
||||
bean.setName("haha");
|
||||
bean.setMap(Utility.ofMap("aa", "bbb"));
|
||||
TreeMap rs = new TreeMap();
|
||||
Reproduce.load(Map.class, TestInterface.class).apply(rs, bean);
|
||||
Copier.load(TestInterface.class, Map.class).apply(bean, rs);
|
||||
System.out.println(JsonConvert.root().convertTo(rs));
|
||||
}
|
||||
|
||||
@@ -59,8 +59,8 @@ public class ReproduceTest {
|
||||
map.put("id", "222");
|
||||
map.put("map", Utility.ofMap("aa", "bbb"));
|
||||
TestBean bean = new TestBean();
|
||||
Reproduce.load(TestInterface.class, Map.class).apply(bean, map);
|
||||
Assertions.assertEquals("{\"id\":222,\"map\":{\"aa\":\"bbb\"},\"time\":0}", JsonConvert.root().convertTo(bean));
|
||||
TestInterface ti = Copier.load(Map.class, TestInterface.class).apply(map, new TestBean());;
|
||||
Assertions.assertEquals("{\"id\":222,\"map\":{\"aa\":\"bbb\"},\"time\":0}", JsonConvert.root().convertTo(ti));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -71,7 +71,7 @@ public class ReproduceTest {
|
||||
map.put("time", "55555");
|
||||
map.put("id", "222");
|
||||
map.put("map", Utility.ofMap("aa", "bbb"));
|
||||
Reproduce.load(TestBean.class, Map.class).apply(bean, map);
|
||||
Copier.load(Map.class, TestBean.class).apply(map, bean);
|
||||
System.out.println(JsonConvert.root().convertTo(bean));
|
||||
map.put("time", 55555L);
|
||||
map.put("id", 222);
|
||||
@@ -86,7 +86,7 @@ public class ReproduceTest {
|
||||
map.put("id", "222");
|
||||
map.put("map", Utility.ofMap("aa", "bbb"));
|
||||
Map rs = new TreeMap();
|
||||
Reproduce.load(Map.class, Map.class).apply(rs, map);
|
||||
Copier.load(Map.class, Map.class).apply(map, rs);
|
||||
System.out.println("Map: " + JsonConvert.root().convertTo(rs));
|
||||
Assertions.assertEquals(JsonConvert.root().convertTo(map), JsonConvert.root().convertTo(rs));
|
||||
}
|
||||
@@ -98,7 +98,7 @@ public class ReproduceTest {
|
||||
bean.time = 55555L;
|
||||
bean.setName(null);
|
||||
bean.setMap(Utility.ofMap("aa", "bbb"));
|
||||
ConcurrentHashMap rs = Reproduce.copy(ConcurrentHashMap.class, bean);
|
||||
ConcurrentHashMap rs = Copier.copy(bean, ConcurrentHashMap.class);
|
||||
System.out.println(JsonConvert.root().convertTo(rs));
|
||||
System.out.println("------------------------------------------");
|
||||
}
|
||||
@@ -111,7 +111,7 @@ public class ReproduceTest {
|
||||
map.put("time", "55555");
|
||||
map.put("id", null);
|
||||
map.put("map", Utility.ofMap("aa", "bbb"));
|
||||
Reproduce.load(TestBean.class, Map.class).apply(bean, map);
|
||||
Copier.load(Map.class, TestBean.class).apply(map, bean);
|
||||
System.out.println(JsonConvert.root().convertTo(bean));
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,7 @@ import org.redkale.util.*;
|
||||
public class UntilTestMain {
|
||||
|
||||
public static void main(String[] args) throws Throwable {
|
||||
reproduce(args);
|
||||
copy(args);
|
||||
attribute(args);
|
||||
aes(args);
|
||||
}
|
||||
@@ -46,17 +46,17 @@ public class UntilTestMain {
|
||||
System.out.println(Utility.binToHexString(secret.getBytes()));
|
||||
}
|
||||
|
||||
public static void reproduce(String[] args) throws Throwable {
|
||||
public static void copy(String[] args) throws Throwable {
|
||||
final TestBean bean = new TestBean();
|
||||
bean.setId(123456);
|
||||
bean.setName("zhangjx");
|
||||
bean.time = 2000;
|
||||
final TestXBean beanx = new TestXBean();
|
||||
Reproduce<TestXBean, TestBean> action1 = Reproduce.create(TestXBean.class, TestBean.class);
|
||||
Reproduce<TestXBean, TestBean> action2 = new Reproduce<TestXBean, TestBean>() {
|
||||
Copier<TestBean, TestXBean> action1 = Copier.create(TestBean.class, TestXBean.class);
|
||||
Copier<TestBean, TestXBean> action2 = new Copier<TestBean, TestXBean>() {
|
||||
|
||||
@Override
|
||||
public TestXBean apply(TestXBean dest, TestBean src) {
|
||||
public TestXBean apply(TestBean src, TestXBean dest) {
|
||||
dest.time = src.time;
|
||||
dest.setId(src.getId());
|
||||
dest.setName(src.getName());
|
||||
@@ -67,13 +67,13 @@ public class UntilTestMain {
|
||||
final int count = 1_000_000;
|
||||
long s = System.nanoTime();
|
||||
for (int i = 0; i < count; i++) {
|
||||
action2.apply(beanx, bean);
|
||||
action2.apply(bean, beanx);
|
||||
}
|
||||
long e = System.nanoTime() - s;
|
||||
System.out.println("静态Reproduce耗时: " + e);
|
||||
s = System.nanoTime();
|
||||
for (int i = 0; i < count; i++) {
|
||||
action1.apply(beanx, bean);
|
||||
action1.apply(bean, beanx);
|
||||
}
|
||||
e = System.nanoTime() - s;
|
||||
System.out.println("动态Reproduce耗时: " + e);
|
||||
|
||||
Reference in New Issue
Block a user