From 9b4433fddf5b401edb0aace8a404ac733b122702 Mon Sep 17 00:00:00 2001
From: 田源 <tianyuan@vci-tech.com>
Date: 星期四, 03 四月 2025 14:35:02 +0800
Subject: [PATCH] 添加非密字段显示

---
 Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/beans/BladeBeanMapEmitter.java |  192 ++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 192 insertions(+), 0 deletions(-)

diff --git a/Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/beans/BladeBeanMapEmitter.java b/Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/beans/BladeBeanMapEmitter.java
new file mode 100644
index 0000000..8455905
--- /dev/null
+++ b/Source/BladeX-Tool/blade-core-tool/src/main/java/org/springblade/core/tool/beans/BladeBeanMapEmitter.java
@@ -0,0 +1,192 @@
+package org.springblade.core.tool.beans;
+
+import org.springblade.core.tool.utils.ReflectUtil;
+import org.springframework.asm.ClassVisitor;
+import org.springframework.asm.Label;
+import org.springframework.asm.Type;
+import org.springframework.cglib.core.*;
+
+import java.beans.PropertyDescriptor;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * 閲嶅啓 cglib BeanMap 澶勭悊鍣�
+ *
+ * @author L.cm
+ */
+class BladeBeanMapEmitter extends ClassEmitter {
+	private static final Type BEAN_MAP = TypeUtils.parseType(BladeBeanMap.class.getName());
+	private static final Type FIXED_KEY_SET = TypeUtils.parseType("org.springframework.cglib.beans.FixedKeySet");
+	private static final Signature CSTRUCT_OBJECT = TypeUtils.parseConstructor("Object");
+	private static final Signature CSTRUCT_STRING_ARRAY = TypeUtils.parseConstructor("String[]");
+	private static final Signature BEAN_MAP_GET = TypeUtils.parseSignature("Object get(Object, Object)");
+	private static final Signature BEAN_MAP_PUT = TypeUtils.parseSignature("Object put(Object, Object, Object)");
+	private static final Signature KEY_SET = TypeUtils.parseSignature("java.util.Set keySet()");
+	private static final Signature NEW_INSTANCE = new Signature("newInstance", BEAN_MAP, new Type[]{Constants.TYPE_OBJECT});
+	private static final Signature GET_PROPERTY_TYPE = TypeUtils.parseSignature("Class getPropertyType(String)");
+
+	public BladeBeanMapEmitter(ClassVisitor v, String className, Class type, int require) {
+		super(v);
+
+		begin_class(Constants.V1_2, Constants.ACC_PUBLIC, className, BEAN_MAP, null, Constants.SOURCE_FILE);
+		EmitUtils.null_constructor(this);
+		EmitUtils.factory_method(this, NEW_INSTANCE);
+		generateConstructor();
+
+		Map<String, PropertyDescriptor> getters = makePropertyMap(ReflectUtil.getBeanGetters(type));
+		Map<String, PropertyDescriptor> setters = makePropertyMap(ReflectUtil.getBeanSetters(type));
+		Map<String, PropertyDescriptor> allProps = new HashMap<>(32);
+		allProps.putAll(getters);
+		allProps.putAll(setters);
+
+		if (require != 0) {
+			for (Iterator it = allProps.keySet().iterator(); it.hasNext(); ) {
+				String name = (String) it.next();
+				if ((((require & BladeBeanMap.REQUIRE_GETTER) != 0) && !getters.containsKey(name)) ||
+					(((require & BladeBeanMap.REQUIRE_SETTER) != 0) && !setters.containsKey(name))) {
+					it.remove();
+					getters.remove(name);
+					setters.remove(name);
+				}
+			}
+		}
+		generateGet(type, getters);
+		generatePut(type, setters);
+
+		String[] allNames = getNames(allProps);
+		generateKeySet(allNames);
+		generateGetPropertyType(allProps, allNames);
+		end_class();
+	}
+
+	private Map<String, PropertyDescriptor> makePropertyMap(PropertyDescriptor[] props) {
+		Map<String, PropertyDescriptor> names = new HashMap<>(16);
+		for (PropertyDescriptor prop : props) {
+			String propName = prop.getName();
+			// 杩囨护 getClass锛孲pring 鐨勫伐鍏风被浼氭嬁鍒拌鏂规硶
+			if (!"class".equals(propName)) {
+				names.put(propName, prop);
+			}
+		}
+		return names;
+	}
+
+	private String[] getNames(Map<String, PropertyDescriptor> propertyMap) {
+		return propertyMap.keySet().toArray(new String[0]);
+	}
+
+	private void generateConstructor() {
+		CodeEmitter e = begin_method(Constants.ACC_PUBLIC, CSTRUCT_OBJECT, null);
+		e.load_this();
+		e.load_arg(0);
+		e.super_invoke_constructor(CSTRUCT_OBJECT);
+		e.return_value();
+		e.end_method();
+	}
+
+	private void generateGet(Class type, final Map<String, PropertyDescriptor> getters) {
+		final CodeEmitter e = begin_method(Constants.ACC_PUBLIC, BEAN_MAP_GET, null);
+		e.load_arg(0);
+		e.checkcast(Type.getType(type));
+		e.load_arg(1);
+		e.checkcast(Constants.TYPE_STRING);
+		EmitUtils.string_switch(e, getNames(getters), Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() {
+			@Override
+			public void processCase(Object key, Label end) {
+				PropertyDescriptor pd = getters.get(key);
+				MethodInfo method = ReflectUtils.getMethodInfo(pd.getReadMethod());
+				e.invoke(method);
+				e.box(method.getSignature().getReturnType());
+				e.return_value();
+			}
+
+			@Override
+			public void processDefault() {
+				e.aconst_null();
+				e.return_value();
+			}
+		});
+		e.end_method();
+	}
+
+	private void generatePut(Class type, final Map<String, PropertyDescriptor> setters) {
+		final CodeEmitter e = begin_method(Constants.ACC_PUBLIC, BEAN_MAP_PUT, null);
+		e.load_arg(0);
+		e.checkcast(Type.getType(type));
+		e.load_arg(1);
+		e.checkcast(Constants.TYPE_STRING);
+		EmitUtils.string_switch(e, getNames(setters), Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() {
+			@Override
+			public void processCase(Object key, Label end) {
+				PropertyDescriptor pd = setters.get(key);
+				if (pd.getReadMethod() == null) {
+					e.aconst_null();
+				} else {
+					MethodInfo read = ReflectUtils.getMethodInfo(pd.getReadMethod());
+					e.dup();
+					e.invoke(read);
+					e.box(read.getSignature().getReturnType());
+				}
+				// move old value behind bean
+				e.swap();
+				// new value
+				e.load_arg(2);
+				MethodInfo write = ReflectUtils.getMethodInfo(pd.getWriteMethod());
+				e.unbox(write.getSignature().getArgumentTypes()[0]);
+				e.invoke(write);
+				e.return_value();
+			}
+
+			@Override
+			public void processDefault() {
+				// fall-through
+			}
+		});
+		e.aconst_null();
+		e.return_value();
+		e.end_method();
+	}
+
+	private void generateKeySet(String[] allNames) {
+		// static initializer
+		declare_field(Constants.ACC_STATIC | Constants.ACC_PRIVATE, "keys", FIXED_KEY_SET, null);
+
+		CodeEmitter e = begin_static();
+		e.new_instance(FIXED_KEY_SET);
+		e.dup();
+		EmitUtils.push_array(e, allNames);
+		e.invoke_constructor(FIXED_KEY_SET, CSTRUCT_STRING_ARRAY);
+		e.putfield("keys");
+		e.return_value();
+		e.end_method();
+
+		// keySet
+		e = begin_method(Constants.ACC_PUBLIC, KEY_SET, null);
+		e.load_this();
+		e.getfield("keys");
+		e.return_value();
+		e.end_method();
+	}
+
+	private void generateGetPropertyType(final Map allProps, String[] allNames) {
+		final CodeEmitter e = begin_method(Constants.ACC_PUBLIC, GET_PROPERTY_TYPE, null);
+		e.load_arg(0);
+		EmitUtils.string_switch(e, allNames, Constants.SWITCH_STYLE_HASH, new ObjectSwitchCallback() {
+			@Override
+			public void processCase(Object key, Label end) {
+				PropertyDescriptor pd = (PropertyDescriptor) allProps.get(key);
+				EmitUtils.load_class(e, Type.getType(pd.getPropertyType()));
+				e.return_value();
+			}
+
+			@Override
+			public void processDefault() {
+				e.aconst_null();
+				e.return_value();
+			}
+		});
+		e.end_method();
+	}
+}

--
Gitblit v1.9.3