优化Copier

This commit is contained in:
redkale
2023-09-21 17:25:36 +08:00
parent 915583d915
commit e60e869fe9
12 changed files with 176 additions and 130 deletions

View File

@@ -25,7 +25,8 @@ import java.lang.annotation.*;
*
* @since Common Annotations 1.2
*
* @deprecated replace by org.redkale.annotation.Priority
* @deprecated replace by {@link org.redkale.annotation.Priority}
*
*/
@Deprecated(since = "2.8.0")
@Target({ElementType.TYPE})

View File

@@ -12,7 +12,7 @@ import java.lang.annotation.*;
*
* @see org.redkale.annotation.Resource
*
* @deprecated replace by org.redkale.annotation.Resource
* @deprecated replace by {@link org.redkale.annotation.Resource}
*/
@Deprecated(since = "2.8.0")
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})

View File

@@ -15,9 +15,9 @@
***************************************************************************** */
package javax.persistence;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.*;
/**
* Specifies whether an entity should be cached if caching is enabled
@@ -33,7 +33,7 @@ import java.lang.annotation.*;
*
* @since Java Persistence 2.0
*
* @deprecated replace by org.redkale.persistence.Cacheable
* @deprecated replace by {@link org.redkale.persistence.Cacheable}
* @see org.redkale.persistence.Cacheable
*/
@Deprecated(since = "2.8.0")

View File

@@ -15,9 +15,9 @@
***************************************************************************** */
package javax.persistence;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Specifies the mapped column for a persistent property or field.
@@ -47,7 +47,7 @@ import static java.lang.annotation.ElementType.*;
*
* @since Java Persistence 1.0
*
* @deprecated replace by org.redkale.persistence.Column
* @deprecated replace by {@link org.redkale.persistence.Column}
*
* @see org.redkale.persistence.Column
*/

View File

@@ -15,9 +15,9 @@
******************************************************************************/
package javax.persistence;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.*;
/**
* Specifies that the class is an entity. This annotation is applied to the
@@ -25,7 +25,7 @@ import java.lang.annotation.*;
*
* @since Java Persistence 1.0
*
* @deprecated replace by org.redkale.persistence.Entity
* @deprecated replace by {@link org.redkale.persistence.Entity}
*
* @see org.redkale.persistence.Entity
*/

View File

@@ -15,9 +15,9 @@
******************************************************************************/
package javax.persistence;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Specifies the primary key of an entity.
@@ -47,7 +47,7 @@ import static java.lang.annotation.ElementType.*;
*
* @since Java Persistence 1.0
*
* @deprecated replace by org.redkale.persistence.Id
* @deprecated replace by {@link org.redkale.persistence.Id}
*
* @see org.redkale.persistence.Id
*/

View File

@@ -14,8 +14,8 @@
***************************************************************************** */
package javax.persistence;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Used in schema generation to specify creation of an index.
@@ -38,7 +38,7 @@ import java.lang.annotation.*;
*
* @since Java Persistence 2.1
*
* @deprecated replace by org.redkale.persistence.Index
* @deprecated replace by {@link org.redkale.persistence.Index}
*
* @see org.redkale.persistence.Index
*

View File

@@ -15,9 +15,9 @@
***************************************************************************** */
package javax.persistence;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.*;
/**
* Specifies the primary table for the annotated entity. Additional
@@ -37,7 +37,7 @@ import java.lang.annotation.*;
*
* @since Java Persistence 1.0
*
* @deprecated replace by org.redkale.persistence.Table
* @deprecated replace by {@link org.redkale.persistence.Table}
*
* @see org.redkale.persistence.Table
*/

View File

@@ -15,9 +15,9 @@
******************************************************************************/
package javax.persistence;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.*;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Specifies that the property or field is not persistent. It is used
@@ -37,7 +37,7 @@ import static java.lang.annotation.ElementType.*;
*
* @since Java Persistence 1.0
*
* @deprecated replace by org.redkale.persistence.Transient
* @deprecated replace by {@link org.redkale.persistence.Transient}
*
* @see org.redkale.persistence.Transient
*/

View File

@@ -15,8 +15,8 @@
***************************************************************************** */
package javax.persistence;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.*;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
/**
* Specifies that a unique constraint is to be included in
@@ -35,7 +35,7 @@ import java.lang.annotation.*;
*
* @since Java Persistence 1.0
*
* @deprecated replace by org.redkale.persistence.UniqueConstraint
* @deprecated replace by {@link org.redkale.persistence.UniqueConstraint}
*
* @see org.redkale.persistence.UniqueConstraint
*

View File

@@ -65,7 +65,7 @@ public final class EntityCache<T> {
private final Copier<T, T> newCopier;
//修改时的复制器, 排除了标记为&#064;Transient或&#064;Column(updatable=false)的字段
private final Copier<T, T> chgCopier;
private final Copier<T, T> uptCopier;
//是否已经全量加载过
private volatile boolean fullloaded;
@@ -110,26 +110,24 @@ public final class EntityCache<T> {
}
}
this.needCopy = !direct;
this.newCopier = Copier.create(type, type, (m) -> {
this.newCopier = Copier.create(type, type, (e, c) -> {
try {
java.lang.reflect.Field field = type.getDeclaredField(m);
return field.getAnnotation(Transient.class) == null && field.getAnnotation(javax.persistence.Transient.class) == null;
} catch (Exception e) {
return e.getAnnotation(Transient.class) == null && e.getAnnotation(javax.persistence.Transient.class) == null;
} catch (Exception ex) {
return true;
}
});
this.chgCopier = Copier.create(type, type, (m) -> {
this.uptCopier = Copier.create(type, type, (e, c) -> {
try {
java.lang.reflect.Field field = type.getDeclaredField(m);
if (field.getAnnotation(Transient.class) != null) {
if (e.getAnnotation(Transient.class) != null) {
return false;
}
if (field.getAnnotation(javax.persistence.Transient.class) != null) {
if (e.getAnnotation(javax.persistence.Transient.class) != null) {
return false;
}
Column column = field.getAnnotation(Column.class);
Column column = e.getAnnotation(Column.class);
return (column == null || column.updatable());
} catch (Exception e) {
} catch (Exception ex) {
return true;
}
});
@@ -874,7 +872,7 @@ public final class EntityCache<T> {
}
tableLock.lock(); //表锁, 可优化成行锁
try {
this.chgCopier.apply(rs, entity);
this.uptCopier.apply(rs, entity);
} finally {
tableLock.unlock();
}

View File

@@ -7,6 +7,7 @@ import java.lang.reflect.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.*;
import java.util.stream.Collectors;
import org.redkale.asm.*;
import static org.redkale.asm.ClassWriter.COMPUTE_FRAMES;
import static org.redkale.asm.Opcodes.*;
@@ -392,7 +393,7 @@ public interface Copier<S, D> extends BiFunction<S, D, D> {
* @param <S> 源类泛型
* @param destClass 目标类名
* @param srcClass 源类名
* @param srcColumnPredicate 需复制的字段名判断
* @param srcColumnPredicate 需复制源类的字段名判断
*
* @return 复制器
*/
@@ -408,7 +409,7 @@ public interface Copier<S, D> extends BiFunction<S, D, D> {
* @param <S> 源类泛型
* @param destClass 目标类名
* @param srcClass 源类名
* @param srcColumnPredicate 需复制的字段名判断
* @param srcColumnPredicate 需复制源类的字段名判断
* @param names 源字段名与目标字段名的映射关系
*
* @return 复制器
@@ -426,7 +427,7 @@ public interface Copier<S, D> extends BiFunction<S, D, D> {
* @param <S> 源类泛型
* @param destClass 目标类名
* @param srcClass 源类名
* @param srcColumnPredicate 需复制的字段名判断
* @param srcColumnPredicate 需复制源类的字段名判断
*
* @return 复制器
*/
@@ -443,7 +444,7 @@ public interface Copier<S, D> extends BiFunction<S, D, D> {
* @param <S> 源类泛型
* @param destClass 目标类名
* @param srcClass 源类名
* @param srcColumnPredicate 需复制的字段名判断
* @param srcColumnPredicate 需复制源类的字段名判断
* @param names 源字段名与目标字段名的映射关系
*
* @return 复制器
@@ -478,7 +479,7 @@ public interface Copier<S, D> extends BiFunction<S, D, D> {
* @param destClass 目标类名
* @param srcClass 源类名
* @param options 可配项
* @param srcColumnPredicate 需复制的字段名判断
* @param srcColumnPredicate 需复制源类的字段名判断
* @param nameAlias 源字段名与目标字段名的映射关系
*
* @return 复制器
@@ -559,6 +560,126 @@ public interface Copier<S, D> extends BiFunction<S, D, D> {
// ------------------------------------------------------------------------------
final boolean destIsMap = Map.class.isAssignableFrom(destClass);
final boolean srcIsMap = Map.class.isAssignableFrom(srcClass);
final Predicate<Class<?>> throwPredicate = e -> !RuntimeException.class.isAssignableFrom(e);
final Map<String, AccessibleObject> elements = new TreeMap<>();
final Map<String, String> destNewNames = new TreeMap<>();
int ingoreCount = 0;
if (srcIsMap) { //Map -> JavaBean
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)) {
ingoreCount++;
continue;
}
final String dfname = nameAlias == null ? sfname : nameAlias.getOrDefault(sfname, sfname);
if (!Objects.equals(sfname, dfname)) {
destNewNames.put(sfname, dfname);
}
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)) {
ingoreCount++;
continue;
}
final String dfname = nameAlias == null ? sfname : nameAlias.getOrDefault(sfname, sfname);
if (!Objects.equals(sfname, dfname)) {
destNewNames.put(sfname, dfname);
}
elements.put(dfname, setter);
}
} else { //JavaBean -> Map/JavaBean
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)) {
ingoreCount++;
continue;
}
final String dfname = nameAlias == null ? sfname : nameAlias.getOrDefault(sfname, sfname);
if (!Objects.equals(sfname, dfname)) {
destNewNames.put(sfname, dfname);
}
elements.put(sfname, field);
}
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)) {
ingoreCount++;
continue;
}
final String dfname = nameAlias == null ? sfname : nameAlias.getOrDefault(sfname, sfname);
if (!Objects.equals(sfname, dfname)) {
destNewNames.put(sfname, dfname);
}
elements.put(sfname, getter);
}
}
StringBuilder extendInfo = new StringBuilder();
if (ingoreCount > 0 || nameAlias != null) {
if (ingoreCount > 0) {
extendInfo.append(elements.keySet().stream().collect(Collectors.joining(",")));
}
if (nameAlias != null) {
if (extendInfo.length() > 0) {
extendInfo.append(";");
}
destNewNames.forEach((k, v) -> extendInfo.append(k).append(':').append(v));
}
}
// ------------------------------------------------------------------------------
final String supDynName = Copier.class.getName().replace('.', '/');
final String destClassName = destClass.getName().replace('.', '/');
final String srcClassName = srcClass.getName().replace('.', '/');
@@ -568,16 +689,14 @@ public interface Copier<S, D> extends BiFunction<S, D, D> {
final String utilClassName = Utility.class.getName().replace('.', '/');
final String newDynName = "org/redkaledyn/copier/_Dyn" + Copier.class.getSimpleName() + "_" + options
+ "__" + srcClass.getName().replace('.', '_').replace('$', '_')
+ "__" + destClass.getName().replace('.', '_').replace('$', '_');
if (srcColumnPredicate == null && nameAlias == null) {
try {
Class clz = RedkaleClassLoader.findDynClass(newDynName.replace('/', '.'));
return (Copier) (clz == null ? loader.loadClass(newDynName.replace('/', '.')) : clz).getDeclaredConstructor().newInstance();
} catch (Throwable ex) {
}
+ "__" + destClass.getName().replace('.', '_').replace('$', '_')
+ (extendInfo.length() == 0 ? "" : Utility.md5Hex(extendInfo.toString()));
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;
@@ -623,49 +742,6 @@ public interface Copier<S, D> extends BiFunction<S, D, D> {
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 = nameAlias == null ? sfname : nameAlias.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 = nameAlias == null ? sfname : nameAlias.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;
@@ -741,23 +817,14 @@ public interface Copier<S, D> extends BiFunction<S, D, D> {
}
Predicate<Class> simpler = t -> t.isPrimitive() || t == String.class || Number.class.isAssignableFrom(t);
for (Map.Entry<String, AccessibleObject> en : elements.entrySet()) {
if (!(en.getValue() instanceof java.lang.reflect.Field)) {
continue;
}
java.lang.reflect.Field field = (java.lang.reflect.Field) en.getValue();
final String sfname = en.getKey();
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 = nameAlias == null ? sfname : nameAlias.getOrDefault(sfname, sfname);
final String dfname = destNewNames.getOrDefault(sfname, sfname);
final Class srcFieldType = field.getType();
final boolean charstr = CharSequence.class.isAssignableFrom(srcFieldType);
if (destIsMap) { //JavaBean -> Map
@@ -914,32 +981,14 @@ public interface Copier<S, D> extends BiFunction<S, D, D> {
}
}
}
for (Map.Entry<String, AccessibleObject> en : elements.entrySet()) {
if (!(en.getValue() instanceof java.lang.reflect.Method)) {
continue;
}
java.lang.reflect.Method getter = (java.lang.reflect.Method) en.getValue();
final String sfname = en.getKey();
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 = nameAlias == null ? sfname : nameAlias.getOrDefault(sfname, sfname);
final String dfname = destNewNames.getOrDefault(sfname, sfname);
final Class srcFieldType = getter.getReturnType();
final boolean charstr = CharSequence.class.isAssignableFrom(srcFieldType);
if (destIsMap) { //srcClass是JavaBean
@@ -1113,9 +1162,7 @@ public interface Copier<S, D> extends BiFunction<S, D, D> {
return defineClass(name, b, 0, b.length);
}
}.loadClass(newDynName.replace('/', '.'), bytes);
if (srcColumnPredicate == null && nameAlias == null) {
RedkaleClassLoader.putDynClass(newDynName.replace('/', '.'), bytes, newClazz);
}
RedkaleClassLoader.putDynClass(newDynName.replace('/', '.'), bytes, newClazz);
RedkaleClassLoader.putReflectionDeclaredConstructors(newClazz, newDynName.replace('/', '.'));
try {
return (Copier) newClazz.getDeclaredConstructor().newInstance();