Prechádzať zdrojové kódy

refactor(SerializedLambda.java):重构方法增加反序列化安全性,优化命名

HCL 6 rokov pred
rodič
commit
11fbaf824c

+ 4 - 4
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/conditions/AbstractLambdaWrapper.java

@@ -19,8 +19,8 @@ import com.baomidou.mybatisplus.core.toolkit.Assert;
 import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
 import com.baomidou.mybatisplus.core.toolkit.LambdaUtils;
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
-import com.baomidou.mybatisplus.core.toolkit.support.Property;
-import com.baomidou.mybatisplus.core.toolkit.support.SerializedLambda;
+import com.baomidou.mybatisplus.core.toolkit.support.lambda.SFunction;
+import com.baomidou.mybatisplus.core.toolkit.support.lambda.SerializedLambda;
 
 import java.util.Map;
 import java.util.Optional;
@@ -36,13 +36,13 @@ import java.util.Optional;
  */
 @SuppressWarnings("serial")
 public abstract class AbstractLambdaWrapper<T, This extends AbstractLambdaWrapper<T, This>>
-    extends AbstractWrapper<T, Property<T, ?>, This> {
+    extends AbstractWrapper<T, SFunction<T, ?>, This> {
 
     private Map<String, String> columnMap = null;
     private boolean initColumnMap = false;
 
     @Override
-    protected String columnToString(Property<T, ?> column) {
+    protected String columnToString(SFunction<T, ?> column) {
         return getColumn(LambdaUtils.resolve(column));
     }
 

+ 2 - 2
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/conditions/query/LambdaQueryWrapper.java

@@ -20,7 +20,7 @@ import com.baomidou.mybatisplus.core.conditions.segments.MergeSegments;
 import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
 import com.baomidou.mybatisplus.core.toolkit.ArrayUtils;
 import com.baomidou.mybatisplus.core.toolkit.TableInfoHelper;
-import com.baomidou.mybatisplus.core.toolkit.support.Property;
+import com.baomidou.mybatisplus.core.toolkit.support.lambda.SFunction;
 
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -70,7 +70,7 @@ public class LambdaQueryWrapper<T> extends AbstractLambdaWrapper<T, LambdaQueryW
      * @param columns 查询字段
      */
     @SafeVarargs
-    public final LambdaQueryWrapper<T> select(Property<T, ?>... columns) {
+    public final LambdaQueryWrapper<T> select(SFunction<T, ?>... columns) {
         if (ArrayUtils.isNotEmpty(columns)) {
             this.sqlSelect = this.columnsToString(columns);
         }

+ 9 - 9
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/conditions/update/LambdaUpdateWrapper.java

@@ -15,19 +15,19 @@
  */
 package com.baomidou.mybatisplus.core.conditions.update;
 
-import static java.util.stream.Collectors.joining;
+import com.baomidou.mybatisplus.core.conditions.AbstractLambdaWrapper;
+import com.baomidou.mybatisplus.core.conditions.segments.MergeSegments;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
+import com.baomidou.mybatisplus.core.toolkit.sql.SqlUtils;
+import com.baomidou.mybatisplus.core.toolkit.support.lambda.SFunction;
 
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicInteger;
 
-import com.baomidou.mybatisplus.core.conditions.AbstractLambdaWrapper;
-import com.baomidou.mybatisplus.core.conditions.segments.MergeSegments;
-import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
-import com.baomidou.mybatisplus.core.toolkit.StringPool;
-import com.baomidou.mybatisplus.core.toolkit.sql.SqlUtils;
-import com.baomidou.mybatisplus.core.toolkit.support.Property;
+import static java.util.stream.Collectors.joining;
 
 /**
  * <p>
@@ -61,11 +61,11 @@ public class LambdaUpdateWrapper<T> extends AbstractLambdaWrapper<T, LambdaUpdat
         return SqlUtils.stripSqlInjection(sqlSet.stream().collect(joining(StringPool.COMMA)));
     }
 
-    public LambdaUpdateWrapper<T> set(Property<T, ?> column, Object val) {
+    public LambdaUpdateWrapper<T> set(SFunction<T, ?> column, Object val) {
         return this.set(true, column, val);
     }
 
-    public LambdaUpdateWrapper<T> set(boolean condition, Property<T, ?> column, Object val) {
+    public LambdaUpdateWrapper<T> set(boolean condition, SFunction<T, ?> column, Object val) {
         if (condition) {
             sqlSet.add(String.format("%s=%s", columnToString(column), formatSql("{0}", val)));
         }

+ 3 - 3
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/LambdaUtils.java

@@ -17,8 +17,8 @@
 package com.baomidou.mybatisplus.core.toolkit;
 
 import com.baomidou.mybatisplus.core.metadata.TableInfo;
-import com.baomidou.mybatisplus.core.toolkit.support.Property;
-import com.baomidou.mybatisplus.core.toolkit.support.SerializedLambda;
+import com.baomidou.mybatisplus.core.toolkit.support.lambda.SFunction;
+import com.baomidou.mybatisplus.core.toolkit.support.lambda.SerializedLambda;
 
 import java.lang.ref.WeakReference;
 import java.util.HashMap;
@@ -52,7 +52,7 @@ public final class LambdaUtils {
      * @param <T>  类型,被调用的 Function 对象的目标类型
      * @return 返回解析后的结果
      */
-    public static <T> SerializedLambda resolve(Property<T, ?> func) {
+    public static <T> SerializedLambda resolve(SFunction<T, ?> func) {
         Class clazz = func.getClass();
         return Optional.ofNullable(FUNC_CACHE.get(clazz))
             .map(WeakReference::get)

+ 5 - 6
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/support/Property.java → mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/support/lambda/SFunction.java

@@ -14,16 +14,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.baomidou.mybatisplus.core.toolkit.support;
+package com.baomidou.mybatisplus.core.toolkit.support.lambda;
 
-import java.io.Serializable;
+import java.util.function.Function;
 
 /**
+ * 支持序列化的 Function
+ *
  * @author miemie
  * @since 2018-05-12
  */
-@FunctionalInterface
-public interface Property<T, R> extends Serializable {
-
-    R apply(T t);
+public interface SFunction<T, R> extends SerializableLambda, Function<T, R> {
 }

+ 13 - 0
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/support/lambda/SerializableLambda.java

@@ -0,0 +1,13 @@
+package com.baomidou.mybatisplus.core.toolkit.support.lambda;
+
+import java.io.Serializable;
+
+/**
+ * 一个序列化标志接口,起着接口占位符的作用,主要用于传递可序列化的 lambda 表达式
+ * 实现该接口可用于快速的实现 lambda 序列化
+ *
+ * @author HCL
+ * Create at 2018/10/17
+ */
+public interface SerializableLambda extends Serializable {
+}

+ 6 - 3
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/support/SerializedLambda.java → mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/support/lambda/SerializedLambda.java

@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.baomidou.mybatisplus.core.toolkit.support;
+package com.baomidou.mybatisplus.core.toolkit.support.lambda;
 
 import com.baomidou.mybatisplus.core.toolkit.ClassUtils;
 import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
@@ -48,12 +48,15 @@ public class SerializedLambda implements Serializable {
     private Object[] capturedArgs;
 
     /**
-     * 通过反序列化转换 class
+     * 通过反序列化转换 lambda 表达式,该方法只能序列化 lambda 表达式,不能序列化接口实现或者正常非 lambda 写法的对象
      *
      * @param lambda lambda对象
      * @return 返回解析后的 SerializedLambda
      */
-    public static SerializedLambda resolve(Property lambda) {
+    public static SerializedLambda resolve(SerializableLambda lambda) {
+        if (!lambda.getClass().isSynthetic()) {
+            throw ExceptionUtils.mpe("该方法仅能传入 lambda 表达式产生的合成类");
+        }
         try (ObjectInputStream objIn = new ObjectInputStream(new ByteArrayInputStream(SerializationUtils.serialize(lambda))) {
             @Override
             protected Class<?> resolveClass(ObjectStreamClass objectStreamClass) throws IOException, ClassNotFoundException {

+ 3 - 3
mybatis-plus-core/src/test/java/com/baomidou/mybatisplus/core/toolkit/LambdaUtilsTest.java

@@ -1,7 +1,7 @@
 package com.baomidou.mybatisplus.core.toolkit;
 
-import com.baomidou.mybatisplus.core.toolkit.support.Property;
-import com.baomidou.mybatisplus.core.toolkit.support.SerializedLambda;
+import com.baomidou.mybatisplus.core.toolkit.support.lambda.SFunction;
+import com.baomidou.mybatisplus.core.toolkit.support.lambda.SerializedLambda;
 import lombok.Getter;
 import org.junit.Assert;
 import org.junit.Test;
@@ -42,7 +42,7 @@ public class LambdaUtilsTest {
 
         // 这个 TYPE 类型和 T 就没有关系了 ;
         // 如果有需要的话,使用 extends 来建立关系,保证class一致,稍微做点编写检查
-        <TYPE extends T> Cond<T> eq(Property<TYPE, ?> prop, Object val) {
+        <TYPE extends T> Cond<T> eq(SFunction<TYPE, ?> prop, Object val) {
             SerializedLambda lambda = LambdaUtils.resolve(prop);
             this.sb.append(lambda.getImplMethodName()).append(" = ").append(val);
             return this;

+ 2 - 2
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/MybatisSqlSessionTemplate.java

@@ -87,8 +87,8 @@ public class MybatisSqlSessionTemplate implements SqlSession, DisposableBean {
     public MybatisSqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType,
                                      PersistenceExceptionTranslator exceptionTranslator) {
 
-        Assert.notNull(sqlSessionFactory, "Property 'sqlSessionFactory' is required");
-        Assert.notNull(executorType, "Property 'executorType' is required");
+        Assert.notNull(sqlSessionFactory, "SFunction 'sqlSessionFactory' is required");
+        Assert.notNull(executorType, "SFunction 'executorType' is required");
 
         this.sqlSessionFactory = sqlSessionFactory;
         this.executorType = executorType;

+ 5 - 5
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/spring/MybatisSqlSessionFactoryBean.java

@@ -378,10 +378,10 @@ public class MybatisSqlSessionFactoryBean implements FactoryBean<SqlSessionFacto
      */
     @Override
     public void afterPropertiesSet() throws Exception {
-        notNull(dataSource, "Property 'dataSource' is required");
-        notNull(sqlSessionFactoryBuilder, "Property 'sqlSessionFactoryBuilder' is required");
+        notNull(dataSource, "SFunction 'dataSource' is required");
+        notNull(sqlSessionFactoryBuilder, "SFunction 'sqlSessionFactoryBuilder' is required");
         state((configuration == null && configLocation == null) || !(configuration != null && configLocation != null),
-            "Property 'configuration' and 'configLocation' can not specified with together");
+            "SFunction 'configuration' and 'configLocation' can not specified with together");
 
         this.sqlSessionFactory = buildSqlSessionFactory();
         //TODO: 3.0 注入到globalConfig
@@ -415,7 +415,7 @@ public class MybatisSqlSessionFactoryBean implements FactoryBean<SqlSessionFacto
             configuration = xmlConfigBuilder.getConfiguration();
         } else {
             if (LOGGER.isDebugEnabled()) {
-                LOGGER.debug("Property 'configuration' or 'configLocation' not specified, using default MyBatis Configuration");
+                LOGGER.debug("SFunction 'configuration' or 'configLocation' not specified, using default MyBatis Configuration");
             }
             // TODO 使用自定义配置
             configuration = new MybatisConfiguration();
@@ -638,7 +638,7 @@ public class MybatisSqlSessionFactoryBean implements FactoryBean<SqlSessionFacto
             }
         } else {
             if (LOGGER.isDebugEnabled()) {
-                LOGGER.debug("Property 'mapperLocations' was not specified or no matching resources found");
+                LOGGER.debug("SFunction 'mapperLocations' was not specified or no matching resources found");
             }
         }
         return sqlSessionFactory;