From 8267d62b7d89e101669e20e66d6b94420fb82c85 Mon Sep 17 00:00:00 2001
From: ludc <ludc@vci-tech.com>
Date: 星期四, 26 十二月 2024 17:26:54 +0800
Subject: [PATCH] 方法重名修改
---
Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/beans/BladeBeanCopier.java | 405 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 405 insertions(+), 0 deletions(-)
diff --git a/Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/beans/BladeBeanCopier.java b/Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/beans/BladeBeanCopier.java
new file mode 100644
index 0000000..0dc0c33
--- /dev/null
+++ b/Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/beans/BladeBeanCopier.java
@@ -0,0 +1,405 @@
+/*
+ * Copyright (c) 2018-2028, DreamLu All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * Neither the name of the dreamlu.net developer nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ * Author: DreamLu 鍗㈡槬姊� (596392912@qq.com)
+ */
+
+package org.springblade.core.tool.beans;
+
+
+import org.springblade.core.tool.utils.BeanUtil;
+import org.springblade.core.tool.utils.ClassUtil;
+import org.springblade.core.tool.utils.ReflectUtil;
+import org.springblade.core.tool.utils.StringUtil;
+import org.springframework.asm.ClassVisitor;
+import org.springframework.asm.Label;
+import org.springframework.asm.Opcodes;
+import org.springframework.asm.Type;
+import org.springframework.cglib.core.*;
+import org.springframework.lang.Nullable;
+import org.springframework.util.ClassUtils;
+
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.security.ProtectionDomain;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * spring cglib 榄旀敼
+ *
+ * <p>
+ * 1. 鏀寔閾惧紡 bean锛屾敮鎸� map
+ * 2. ClassLoader 璺� target 淇濇寔涓�鑷�
+ * </p>
+ *
+ * @author L.cm
+ */
+public abstract class BladeBeanCopier {
+ private static final Type CONVERTER = TypeUtils.parseType("org.springframework.cglib.core.Converter");
+ private static final Type BEAN_COPIER = TypeUtils.parseType(BladeBeanCopier.class.getName());
+ private static final Type BEAN_MAP = TypeUtils.parseType(Map.class.getName());
+ private static final Signature COPY = new Signature("copy", Type.VOID_TYPE, new Type[]{Constants.TYPE_OBJECT, Constants.TYPE_OBJECT, CONVERTER});
+ private static final Signature CONVERT = TypeUtils.parseSignature("Object convert(Object, Class, Object)");
+ private static final Signature BEAN_MAP_GET = TypeUtils.parseSignature("Object get(Object)");
+ private static final Type CLASS_UTILS = TypeUtils.parseType(ClassUtils.class.getName());
+ private static final Signature IS_ASSIGNABLE_VALUE = TypeUtils.parseSignature("boolean isAssignableValue(Class, Object)");
+ /**
+ * The map to store {@link BladeBeanCopier} of source type and class type for copy.
+ */
+ private static final ConcurrentMap<BladeBeanCopierKey, BladeBeanCopier> BEAN_COPIER_MAP = new ConcurrentHashMap<>();
+
+ public static BladeBeanCopier create(Class source, Class target, boolean useConverter) {
+ return BladeBeanCopier.create(source, target, useConverter, false);
+ }
+
+ public static BladeBeanCopier create(Class source, Class target, boolean useConverter, boolean nonNull) {
+ BladeBeanCopierKey copierKey = new BladeBeanCopierKey(source, target, useConverter, nonNull);
+ // 鍒╃敤 ConcurrentMap 缂撳瓨 鎻愰珮鎬ц兘锛屾帴杩� 鐩存帴 get set
+ return BEAN_COPIER_MAP.computeIfAbsent(copierKey, key -> {
+ Generator gen = new Generator();
+ gen.setSource(key.getSource());
+ gen.setTarget(key.getTarget());
+ gen.setUseConverter(key.isUseConverter());
+ gen.setNonNull(key.isNonNull());
+ return gen.create(key);
+ });
+ }
+
+ /**
+ * Bean copy
+ *
+ * @param from from Bean
+ * @param to to Bean
+ * @param converter Converter
+ */
+ abstract public void copy(Object from, Object to, @Nullable Converter converter);
+
+ public static class Generator extends AbstractClassGenerator {
+ private static final Source SOURCE = new Source(BladeBeanCopier.class.getName());
+ private Class source;
+ private Class target;
+ private boolean useConverter;
+ private boolean nonNull;
+
+ Generator() {
+ super(SOURCE);
+ }
+
+ public void setSource(Class source) {
+ if (!Modifier.isPublic(source.getModifiers())) {
+ setNamePrefix(source.getName());
+ }
+ this.source = source;
+ }
+
+ public void setTarget(Class target) {
+ if (!Modifier.isPublic(target.getModifiers())) {
+ setNamePrefix(target.getName());
+ }
+ this.target = target;
+ }
+
+ public void setUseConverter(boolean useConverter) {
+ this.useConverter = useConverter;
+ }
+
+ public void setNonNull(boolean nonNull) {
+ this.nonNull = nonNull;
+ }
+
+ @Override
+ protected ClassLoader getDefaultClassLoader() {
+ // L.cm 淇濊瘉 鍜� 杩斿洖浣跨敤鍚屼竴涓� ClassLoader
+ return target.getClassLoader();
+ }
+
+ @Override
+ protected ProtectionDomain getProtectionDomain() {
+ return ReflectUtils.getProtectionDomain(source);
+ }
+
+ @Override
+ public BladeBeanCopier create(Object key) {
+ return (BladeBeanCopier) super.create(key);
+ }
+
+ @Override
+ public void generateClass(ClassVisitor v) {
+ Type sourceType = Type.getType(source);
+ Type targetType = Type.getType(target);
+ ClassEmitter ce = new ClassEmitter(v);
+ ce.begin_class(Constants.V1_2,
+ Constants.ACC_PUBLIC,
+ getClassName(),
+ BEAN_COPIER,
+ null,
+ Constants.SOURCE_FILE);
+
+ EmitUtils.null_constructor(ce);
+ CodeEmitter e = ce.begin_method(Constants.ACC_PUBLIC, COPY, null);
+
+ // map 鍗曠嫭澶勭悊
+ if (Map.class.isAssignableFrom(source)) {
+ generateClassFormMap(ce, e, sourceType, targetType);
+ return;
+ }
+
+ // 2018.12.27 by L.cm 鏀寔閾惧紡 bean
+ // 娉ㄦ剰锛氭澶勯渶鍏煎閾惧紡bean 浣跨敤浜� spring 鐨勬柟娉曪紝姣旇緝鑰楁椂
+ PropertyDescriptor[] getters = ReflectUtil.getBeanGetters(source);
+ PropertyDescriptor[] setters = ReflectUtil.getBeanSetters(target);
+ Map<String, PropertyDescriptor> names = new HashMap<>(16);
+ for (PropertyDescriptor getter : getters) {
+ names.put(getter.getName(), getter);
+ }
+
+ Local targetLocal = e.make_local();
+ Local sourceLocal = e.make_local();
+ e.load_arg(1);
+ e.checkcast(targetType);
+ e.store_local(targetLocal);
+ e.load_arg(0);
+ e.checkcast(sourceType);
+ e.store_local(sourceLocal);
+
+ for (PropertyDescriptor setter : setters) {
+ String propName = setter.getName();
+
+ CopyProperty targetIgnoreCopy = ReflectUtil.getAnnotation(target, propName, CopyProperty.class);
+ // set 涓婃湁蹇界暐鐨� 娉ㄨВ
+ if (targetIgnoreCopy != null) {
+ if (targetIgnoreCopy.ignore()) {
+ continue;
+ }
+ // 娉ㄨВ涓婄殑鍒悕锛屽鏋滃埆鍚嶄笉涓虹┖锛屼娇鐢ㄥ埆鍚�
+ String aliasTargetPropName = targetIgnoreCopy.value();
+ if (StringUtil.isNotBlank(aliasTargetPropName)) {
+ propName = aliasTargetPropName;
+ }
+ }
+ // 鎵惧埌瀵瑰簲鐨� get
+ PropertyDescriptor getter = names.get(propName);
+ // 娌℃湁 get 璺冲嚭
+ if (getter == null) {
+ continue;
+ }
+
+ MethodInfo read = ReflectUtils.getMethodInfo(getter.getReadMethod());
+ Method writeMethod = setter.getWriteMethod();
+ MethodInfo write = ReflectUtils.getMethodInfo(writeMethod);
+ Type returnType = read.getSignature().getReturnType();
+ Type setterType = write.getSignature().getArgumentTypes()[0];
+ Class<?> getterPropertyType = getter.getPropertyType();
+ Class<?> setterPropertyType = setter.getPropertyType();
+
+ // L.cm 2019.01.12 浼樺寲閫昏緫锛屽厛鍒ゆ柇绫诲瀷锛岀被鍨嬩竴鑷寸洿鎺� set锛屼笉鍚屽啀鍒ゆ柇 鏄惁 绫诲瀷杞崲
+ // nonNull Label
+ Label l0 = e.make_label();
+ // 鍒ゆ柇绫诲瀷鏄惁涓�鑷达紝鍖呮嫭 鍖呰绫诲瀷
+ if (ClassUtil.isAssignable(setterPropertyType, getterPropertyType)) {
+ // 2018.12.27 by L.cm 鏀寔閾惧紡 bean
+ e.load_local(targetLocal);
+ e.load_local(sourceLocal);
+ e.invoke(read);
+ boolean getterIsPrimitive = getterPropertyType.isPrimitive();
+ boolean setterIsPrimitive = setterPropertyType.isPrimitive();
+
+ if (nonNull) {
+ // 闇�瑕佽惤鏍堬紝寮哄埗瑁呯
+ e.box(returnType);
+ Local var = e.make_local();
+ e.store_local(var);
+ e.load_local(var);
+ // nonNull Label
+ e.ifnull(l0);
+ e.load_local(targetLocal);
+ e.load_local(var);
+ // 闇�瑕佽惤鏍堬紝寮哄埗鎷嗙
+ e.unbox_or_zero(setterType);
+ } else {
+ // 濡傛灉 get 涓哄師濮嬬被鍨嬶紝闇�瑕佽绠�
+ if (getterIsPrimitive && !setterIsPrimitive) {
+ e.box(returnType);
+ }
+ // 濡傛灉 set 涓哄師濮嬬被鍨嬶紝闇�瑕佹媶绠�
+ if (!getterIsPrimitive && setterIsPrimitive) {
+ e.unbox_or_zero(setterType);
+ }
+ }
+
+ // 鏋勯�� set 鏂规硶
+ invokeWrite(e, write, writeMethod, nonNull, l0);
+ } else if (useConverter) {
+ e.load_local(targetLocal);
+ e.load_arg(2);
+ e.load_local(sourceLocal);
+ e.invoke(read);
+ e.box(returnType);
+
+ if (nonNull) {
+ Local var = e.make_local();
+ e.store_local(var);
+ e.load_local(var);
+ e.ifnull(l0);
+ e.load_local(targetLocal);
+ e.load_arg(2);
+ e.load_local(var);
+ }
+
+ EmitUtils.load_class(e, setterType);
+ // 鏇存敼鎴愪簡灞炴�у悕锛屼箣鍓嶆槸 set 鏂规硶鍚�
+ e.push(propName);
+ e.invoke_interface(CONVERTER, CONVERT);
+ e.unbox_or_zero(setterType);
+
+ // 鏋勯�� set 鏂规硶
+ invokeWrite(e, write, writeMethod, nonNull, l0);
+ }
+ }
+ e.return_value();
+ e.end_method();
+ ce.end_class();
+ }
+
+ private static void invokeWrite(CodeEmitter e, MethodInfo write, Method writeMethod, boolean nonNull, Label l0) {
+ // 杩斿洖鍊硷紝鍒ゆ柇 閾惧紡 bean
+ Class<?> returnType = writeMethod.getReturnType();
+ e.invoke(write);
+ // 閾惧紡 bean锛屾湁杩斿洖鍊奸渶瑕� pop
+ if (!returnType.equals(Void.TYPE)) {
+ e.pop();
+ }
+ if (nonNull) {
+ e.visitLabel(l0);
+ }
+ }
+
+ @Override
+ protected Object firstInstance(Class type) {
+ return BeanUtil.newInstance(type);
+ }
+
+ @Override
+ protected Object nextInstance(Object instance) {
+ return instance;
+ }
+
+ /**
+ * 澶勭悊 map 鐨� copy
+ * @param ce ClassEmitter
+ * @param e CodeEmitter
+ * @param sourceType sourceType
+ * @param targetType targetType
+ */
+ public void generateClassFormMap(ClassEmitter ce, CodeEmitter e, Type sourceType, Type targetType) {
+ // 2018.12.27 by L.cm 鏀寔閾惧紡 bean
+ PropertyDescriptor[] setters = ReflectUtil.getBeanSetters(target);
+
+ // 鍏ュ彛鍙橀噺
+ Local targetLocal = e.make_local();
+ Local sourceLocal = e.make_local();
+ e.load_arg(1);
+ e.checkcast(targetType);
+ e.store_local(targetLocal);
+ e.load_arg(0);
+ e.checkcast(sourceType);
+ e.store_local(sourceLocal);
+ Type mapBox = Type.getType(Object.class);
+
+ for (PropertyDescriptor setter : setters) {
+ String propName = setter.getName();
+
+ // set 涓婃湁蹇界暐鐨� 娉ㄨВ
+ CopyProperty targetIgnoreCopy = ReflectUtil.getAnnotation(target, propName, CopyProperty.class);
+ if (targetIgnoreCopy != null) {
+ if (targetIgnoreCopy.ignore()) {
+ continue;
+ }
+ // 娉ㄨВ涓婄殑鍒悕
+ String aliasTargetPropName = targetIgnoreCopy.value();
+ if (StringUtil.isNotBlank(aliasTargetPropName)) {
+ propName = aliasTargetPropName;
+ }
+ }
+
+ Method writeMethod = setter.getWriteMethod();
+ MethodInfo write = ReflectUtils.getMethodInfo(writeMethod);
+ Type setterType = write.getSignature().getArgumentTypes()[0];
+
+ e.load_local(targetLocal);
+ e.load_local(sourceLocal);
+
+ e.push(propName);
+ // 鎵ц map get
+ e.invoke_interface(BEAN_MAP, BEAN_MAP_GET);
+ // box 瑁呯锛岄伩鍏� array[] 鏁扮粍闂
+ e.box(mapBox);
+
+ // 鐢熸垚鍙橀噺
+ Local var = e.make_local();
+ e.store_local(var);
+ e.load_local(var);
+
+ // 鍏堝垽鏂� 涓嶄负null锛岀劧鍚庡仛绫诲瀷鍒ゆ柇
+ Label l0 = e.make_label();
+ e.ifnull(l0);
+ EmitUtils.load_class(e, setterType);
+ e.load_local(var);
+ // ClassUtils.isAssignableValue(Integer.class, id)
+ e.invoke_static(CLASS_UTILS, IS_ASSIGNABLE_VALUE);
+ Label l1 = new Label();
+ // 杩斿洖鍊硷紝鍒ゆ柇 閾惧紡 bean
+ Class<?> returnType = writeMethod.getReturnType();
+ if (useConverter) {
+ e.if_jump(Opcodes.IFEQ, l1);
+ e.load_local(targetLocal);
+ e.load_local(var);
+ e.unbox_or_zero(setterType);
+ e.invoke(write);
+ if (!returnType.equals(Void.TYPE)) {
+ e.pop();
+ }
+ e.goTo(l0);
+ e.visitLabel(l1);
+ e.load_local(targetLocal);
+ e.load_arg(2);
+ e.load_local(var);
+ EmitUtils.load_class(e, setterType);
+ e.push(propName);
+ e.invoke_interface(CONVERTER, CONVERT);
+ e.unbox_or_zero(setterType);
+ e.invoke(write);
+ } else {
+ e.if_jump(Opcodes.IFEQ, l0);
+ e.load_local(targetLocal);
+ e.load_local(var);
+ e.unbox_or_zero(setterType);
+ e.invoke(write);
+ }
+ // 杩斿洖鍊硷紝鍒ゆ柇 閾惧紡 bean
+ if (!returnType.equals(Void.TYPE)) {
+ e.pop();
+ }
+ e.visitLabel(l0);
+ }
+ e.return_value();
+ e.end_method();
+ ce.end_class();
+ }
+ }
+}
--
Gitblit v1.9.3