smallchill 6 anni fa
parent
commit
bac9c5e02e

+ 0 - 4
blade-core-log/src/main/java/org/springblade/core/log/model/LogApi.java

@@ -100,10 +100,6 @@ public class LogApi implements Serializable {
 	 * 执行时间
 	 */
 	private String time;
-	/**
-	 * 异常信息
-	 */
-	private String exception;
 
 	/**
 	 * 创建人

+ 33 - 0
blade-core-log/src/main/java/org/springblade/core/log/model/LogApiVo.java

@@ -0,0 +1,33 @@
+/**
+ * Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springblade.core.log.model;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * LogApi视图实体类
+ *
+ * @author smallchill
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class LogApiVo extends LogApi {
+	private static final long serialVersionUID = 1L;
+
+	private String strId;
+
+}

+ 33 - 0
blade-core-log/src/main/java/org/springblade/core/log/model/LogErrorVo.java

@@ -0,0 +1,33 @@
+/**
+ * Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springblade.core.log.model;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * LogError视图实体类
+ *
+ * @author smallchill
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class LogErrorVo extends LogError {
+	private static final long serialVersionUID = 1L;
+
+	private String strId;
+
+}

+ 33 - 0
blade-core-log/src/main/java/org/springblade/core/log/model/LogUsualVo.java

@@ -0,0 +1,33 @@
+/**
+ * Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.springblade.core.log.model;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+/**
+ * LogUsual视图实体类
+ *
+ * @author smallchill
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class LogUsualVo extends LogUsual {
+	private static final long serialVersionUID = 1L;
+
+	private String strId;
+
+}

+ 184 - 0
blade-core-tool/src/main/java/org/springblade/core/tool/support/BladeBeanCopier.java

@@ -0,0 +1,184 @@
+package org.springblade.core.tool.support;
+
+import org.springblade.core.tool.utils.BeanUtil;
+import org.springframework.asm.ClassVisitor;
+import org.springframework.asm.Type;
+import org.springframework.cglib.core.*;
+
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.Modifier;
+import java.security.ProtectionDomain;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * spring cglib 魔改
+ *
+ * <p>
+ *     1. 支持链式 bean
+ *     2. 自定义的 BeanCopier 解决 spring boot 和 cglib ClassLoader classLoader 不一致的问题
+ * </p>
+ *
+ * @author L.cm
+ */
+public abstract class BladeBeanCopier {
+	private static final BeanCopierKey KEY_FACTORY = (BeanCopierKey) KeyFactory.create(BeanCopierKey.class);
+	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 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)");
+
+	interface BeanCopierKey {
+		Object newInstance(String source, String target, boolean useConverter);
+	}
+
+	public static BladeBeanCopier create(Class source, Class target, boolean useConverter) {
+		return BladeBeanCopier.create(source, target, null, useConverter);
+	}
+
+	public static BladeBeanCopier create(Class source, Class target, ClassLoader classLoader, boolean useConverter) {
+		Generator gen;
+		if (classLoader == null) {
+			gen = new Generator();
+		} else {
+			gen = new Generator(classLoader);
+		}
+		gen.setSource(source);
+		gen.setTarget(target);
+		gen.setUseConverter(useConverter);
+		return gen.create();
+	}
+
+	abstract public void copy(Object from, Object to, Converter converter);
+
+	public static class Generator extends AbstractClassGenerator {
+		private static final Source SOURCE = new Source(BladeBeanCopier.class.getName());
+		private final ClassLoader classLoader;
+		private Class source;
+		private Class target;
+		private boolean useConverter;
+
+		Generator() {
+			super(SOURCE);
+			this.classLoader = null;
+		}
+
+		Generator(ClassLoader classLoader) {
+			super(SOURCE);
+			this.classLoader = classLoader;
+		}
+
+		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;
+		}
+
+		@Override
+		protected ClassLoader getDefaultClassLoader() {
+			return target.getClassLoader();
+		}
+
+		@Override
+		protected ProtectionDomain getProtectionDomain() {
+			return ReflectUtils.getProtectionDomain(source);
+		}
+
+		public BladeBeanCopier create() {
+			Object key = KEY_FACTORY.newInstance(source.getName(), target.getName(), useConverter);
+			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);
+
+			// 2018.12.27 by L.cm 支持链式 bean
+			PropertyDescriptor[] getters = BeanUtil.getBeanGetters(source);
+			PropertyDescriptor[] setters = BeanUtil.getBeanSetters(target);
+			Map<String, Object> names = new HashMap<>();
+			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 (int i = 0; i < setters.length; i++) {
+				PropertyDescriptor setter = setters[i];
+				PropertyDescriptor getter = (PropertyDescriptor) names.get(setter.getName());
+				if (getter != null) {
+					MethodInfo read = ReflectUtils.getMethodInfo(getter.getReadMethod());
+					MethodInfo write = ReflectUtils.getMethodInfo(setter.getWriteMethod());
+					if (useConverter) {
+						Type setterType = write.getSignature().getArgumentTypes()[0];
+						e.load_local(targetLocal);
+						e.load_arg(2);
+						e.load_local(sourceLocal);
+						e.invoke(read);
+						e.box(read.getSignature().getReturnType());
+						EmitUtils.load_class(e, setterType);
+						e.push(write.getSignature().getName());
+						e.invoke_interface(CONVERTER, CONVERT);
+						e.unbox_or_zero(setterType);
+						e.invoke(write);
+					} else if (compatible(getter, setter)) {
+						// 2018.12.27 by L.cm 支持链式 bean
+						e.load_local(targetLocal);
+						e.load_local(sourceLocal);
+						e.invoke(read);
+						e.invoke(write);
+					}
+				}
+			}
+			e.return_value();
+			e.end_method();
+			ce.end_class();
+		}
+
+		private static boolean compatible(PropertyDescriptor getter, PropertyDescriptor setter) {
+			// TODO: allow automatic widening conversions?
+			return setter.getPropertyType().isAssignableFrom(getter.getPropertyType());
+		}
+
+		@Override
+		protected Object firstInstance(Class type) {
+			return ReflectUtils.newInstance(type);
+		}
+
+		@Override
+		protected Object nextInstance(Object instance) {
+			return instance;
+		}
+	}
+}

+ 46 - 3
blade-core-tool/src/main/java/org/springblade/core/tool/utils/BeanUtil.java

@@ -17,12 +17,16 @@ package org.springblade.core.tool.utils;
 
 
 import org.springblade.core.tool.support.BeanProperty;
+import org.springblade.core.tool.support.BladeBeanCopier;
 import org.springframework.beans.BeansException;
-import org.springframework.cglib.beans.BeanCopier;
 import org.springframework.cglib.beans.BeanGenerator;
 import org.springframework.cglib.beans.BeanMap;
+import org.springframework.cglib.core.CodeGenerationException;
 import org.springframework.util.Assert;
 
+import java.beans.PropertyDescriptor;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Map;
 
 /**
@@ -105,7 +109,7 @@ public class BeanUtil extends org.springframework.beans.BeanUtils {
 	 * @return T
 	 */
 	public static <T> T copy(Object source, Class<T> clazz) {
-		BeanCopier copier = BeanCopier.create(source.getClass(), clazz, false);
+		BladeBeanCopier copier = BladeBeanCopier.create(source.getClass(), clazz, false);
 
 		T to = newInstance(clazz);
 		copier.copy(source, to, null);
@@ -121,7 +125,7 @@ public class BeanUtil extends org.springframework.beans.BeanUtils {
 	 * @param targetBean 需要赋值的对象
 	 */
 	public static void copy(Object source, Object targetBean) {
-		BeanCopier copier = BeanCopier
+		BladeBeanCopier copier = BladeBeanCopier
 			.create(source.getClass(), targetBean.getClass(), false);
 
 		copier.copy(source, targetBean, null);
@@ -197,4 +201,43 @@ public class BeanUtil extends org.springframework.beans.BeanUtils {
 		return generator.create();
 	}
 
+	/**
+	 * 获取 Bean 的所有 get方法
+	 * @param type 类
+	 * @return PropertyDescriptor数组
+	 */
+	public static PropertyDescriptor[] getBeanGetters(Class type) {
+		return getPropertiesHelper(type, true, false);
+	}
+
+	/**
+	 * 获取 Bean 的所有 set方法
+	 * @param type 类
+	 * @return PropertyDescriptor数组
+	 */
+	public static PropertyDescriptor[] getBeanSetters(Class type) {
+		return getPropertiesHelper(type, false, true);
+	}
+
+	private static PropertyDescriptor[] getPropertiesHelper(Class type, boolean read, boolean write) {
+		try {
+			PropertyDescriptor[] all = BeanUtil.getPropertyDescriptors(type);
+			if (read && write) {
+				return all;
+			} else {
+				List<PropertyDescriptor> properties = new ArrayList<>(all.length);
+				for (PropertyDescriptor pd : all) {
+					if (read && pd.getReadMethod() != null) {
+						properties.add(pd);
+					} else if (write && pd.getWriteMethod() != null) {
+						properties.add(pd);
+					}
+				}
+				return properties.toArray(new PropertyDescriptor[0]);
+			}
+		} catch (BeansException ex) {
+			throw new CodeGenerationException(ex);
+		}
+	}
+
 }