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