소스 검색

jdk1.8下computeIfAbsent性能bug.

nieqiuqiu 5 년 전
부모
커밋
091ba445f7

+ 2 - 1
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/handlers/MybatisEnumTypeHandler.java

@@ -18,6 +18,7 @@ package com.baomidou.mybatisplus.core.handlers;
 import com.baomidou.mybatisplus.annotation.EnumValue;
 import com.baomidou.mybatisplus.annotation.EnumValue;
 import com.baomidou.mybatisplus.annotation.IEnum;
 import com.baomidou.mybatisplus.annotation.IEnum;
 import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
 import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
+import com.baomidou.mybatisplus.core.toolkit.Maps;
 import org.apache.ibatis.reflection.DefaultReflectorFactory;
 import org.apache.ibatis.reflection.DefaultReflectorFactory;
 import org.apache.ibatis.reflection.MetaClass;
 import org.apache.ibatis.reflection.MetaClass;
 import org.apache.ibatis.reflection.ReflectorFactory;
 import org.apache.ibatis.reflection.ReflectorFactory;
@@ -86,7 +87,7 @@ public class MybatisEnumTypeHandler<E extends Enum<E>> extends BaseTypeHandler<E
     public static Optional<String> findEnumValueFieldName(Class<?> clazz) {
     public static Optional<String> findEnumValueFieldName(Class<?> clazz) {
         if (clazz != null && clazz.isEnum()) {
         if (clazz != null && clazz.isEnum()) {
             String className = clazz.getName();
             String className = clazz.getName();
-            return Optional.ofNullable(TABLE_METHOD_OF_ENUM_TYPES.computeIfAbsent(className, key -> {
+            return Optional.ofNullable(Maps.computeIfAbsent(TABLE_METHOD_OF_ENUM_TYPES, className, key -> {
                 Optional<Field> optional = Arrays.stream(clazz.getDeclaredFields())
                 Optional<Field> optional = Arrays.stream(clazz.getDeclaredFields())
                     .filter(field -> field.isAnnotationPresent(EnumValue.class))
                     .filter(field -> field.isAnnotationPresent(EnumValue.class))
                     .findFirst();
                     .findFirst();

+ 1 - 1
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/metadata/TableInfoHelper.java

@@ -112,7 +112,7 @@ public class TableInfoHelper {
      * @return 数据库表反射信息
      * @return 数据库表反射信息
      */
      */
     public synchronized static TableInfo initTableInfo(MapperBuilderAssistant builderAssistant, Class<?> clazz) {
     public synchronized static TableInfo initTableInfo(MapperBuilderAssistant builderAssistant, Class<?> clazz) {
-        return TABLE_INFO_CACHE.computeIfAbsent(clazz, (key) -> {
+        return Maps.computeIfAbsent(TABLE_INFO_CACHE, clazz, (key) -> {
             /* 没有获取到缓存信息,则初始化 */
             /* 没有获取到缓存信息,则初始化 */
             TableInfo tableInfo = new TableInfo(key);
             TableInfo tableInfo = new TableInfo(key);
             GlobalConfig globalConfig;
             GlobalConfig globalConfig;

+ 2 - 1
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/override/MybatisMapperProxy.java

@@ -15,6 +15,7 @@
  */
  */
 package com.baomidou.mybatisplus.core.override;
 package com.baomidou.mybatisplus.core.override;
 
 
+import com.baomidou.mybatisplus.core.toolkit.Maps;
 import org.apache.ibatis.binding.MapperProxy;
 import org.apache.ibatis.binding.MapperProxy;
 import org.apache.ibatis.reflection.ExceptionUtil;
 import org.apache.ibatis.reflection.ExceptionUtil;
 import org.apache.ibatis.session.SqlSession;
 import org.apache.ibatis.session.SqlSession;
@@ -97,7 +98,7 @@ public class MybatisMapperProxy<T> implements InvocationHandler, Serializable {
     }
     }
 
 
     private MybatisMapperMethod cachedMapperMethod(Method method) {
     private MybatisMapperMethod cachedMapperMethod(Method method) {
-        return methodCache.computeIfAbsent(method,
+        return Maps.computeIfAbsent(methodCache, method,
             k -> new MybatisMapperMethod(mapperInterface, method, sqlSession.getConfiguration()));
             k -> new MybatisMapperMethod(mapperInterface, method, sqlSession.getConfiguration()));
     }
     }
 
 

+ 1 - 1
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/GlobalConfigUtils.java

@@ -83,7 +83,7 @@ public class GlobalConfigUtils {
     public static GlobalConfig getGlobalConfig(Configuration configuration) {
     public static GlobalConfig getGlobalConfig(Configuration configuration) {
         Assert.notNull(configuration, "Error: You need Initialize MybatisConfiguration !");
         Assert.notNull(configuration, "Error: You need Initialize MybatisConfiguration !");
         final String key = Integer.toHexString(configuration.hashCode());
         final String key = Integer.toHexString(configuration.hashCode());
-        return GLOBAL_CONFIG.computeIfAbsent(key, k -> defaults());
+        return Maps.computeIfAbsent(GLOBAL_CONFIG, key, k -> defaults());
     }
     }
 
 
     public static IKeyGenerator getKeyGenerator(Configuration configuration) {
     public static IKeyGenerator getKeyGenerator(Configuration configuration) {

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

@@ -119,7 +119,7 @@ public final class LambdaUtils {
      * @return 缓存 map
      * @return 缓存 map
      */
      */
     public static Map<String, ColumnCache> getColumnMap(Class<?> clazz) {
     public static Map<String, ColumnCache> getColumnMap(Class<?> clazz) {
-        return COLUMN_CACHE_MAP.computeIfAbsent(clazz.getName(), key -> {
+        return Maps.computeIfAbsent(COLUMN_CACHE_MAP, clazz.getName(), key -> {
             TableInfo info = TableInfoHelper.getTableInfo(clazz);
             TableInfo info = TableInfoHelper.getTableInfo(clazz);
             return info == null ? null : createColumnCacheMap(info);
             return info == null ? null : createColumnCacheMap(info);
         });
         });

+ 24 - 0
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/Maps.java

@@ -16,6 +16,9 @@
 package com.baomidou.mybatisplus.core.toolkit;
 package com.baomidou.mybatisplus.core.toolkit;
 
 
 import java.util.HashMap;
 import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.function.Function;
 
 
 /**
 /**
  * com.google.common.collect.Maps
  * com.google.common.collect.Maps
@@ -33,6 +36,27 @@ public final class Maps {
         return new HashMap<>(capacity(expectedSize));
         return new HashMap<>(capacity(expectedSize));
     }
     }
 
 
+    /**
+     * 用来过渡下Jdk1.8下ConcurrentHashMap的性能bug
+     * https://bugs.openjdk.java.net/browse/JDK-8161372
+     *
+     * @param concurrentHashMap
+     * @param key
+     * @param mappingFunction
+     * @param <K>
+     * @param <V>
+     * @since 3.3.3
+     * @return V
+     */
+    public static <K, V> V computeIfAbsent(Map<K, V> concurrentHashMap, K key, Function<? super K, ? extends V> mappingFunction) {
+        Objects.requireNonNull(concurrentHashMap);
+        V v = concurrentHashMap.get(key);
+        if (v != null) {
+            return v;
+        }
+        return concurrentHashMap.computeIfAbsent(key, mappingFunction);
+    }
+
     /**
     /**
      * Returns a capacity that is sufficient to keep the map from being resized as
      * Returns a capacity that is sufficient to keep the map from being resized as
      * long as it grows no larger than expectedSize and the load factor is >= its
      * long as it grows no larger than expectedSize and the load factor is >= its

+ 1 - 1
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/ReflectionKit.java

@@ -214,7 +214,7 @@ public final class ReflectionKit {
         if (Objects.isNull(clazz)) {
         if (Objects.isNull(clazz)) {
             return Collections.emptyList();
             return Collections.emptyList();
         }
         }
-        return CLASS_FIELD_CACHE.computeIfAbsent(clazz, k -> {
+        return Maps.computeIfAbsent(CLASS_FIELD_CACHE, clazz, k -> {
             Field[] fields = k.getDeclaredFields();
             Field[] fields = k.getDeclaredFields();
             List<Field> superFields = new ArrayList<>();
             List<Field> superFields = new ArrayList<>();
             Class<?> currentClass = k.getSuperclass();
             Class<?> currentClass = k.getSuperclass();

+ 2 - 1
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/handlers/MybatisEnumTypeHandler.java

@@ -18,6 +18,7 @@ package com.baomidou.mybatisplus.extension.handlers;
 import com.baomidou.mybatisplus.annotation.EnumValue;
 import com.baomidou.mybatisplus.annotation.EnumValue;
 import com.baomidou.mybatisplus.annotation.IEnum;
 import com.baomidou.mybatisplus.annotation.IEnum;
 import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
 import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
+import com.baomidou.mybatisplus.core.toolkit.Maps;
 import org.apache.ibatis.reflection.DefaultReflectorFactory;
 import org.apache.ibatis.reflection.DefaultReflectorFactory;
 import org.apache.ibatis.reflection.MetaClass;
 import org.apache.ibatis.reflection.MetaClass;
 import org.apache.ibatis.reflection.ReflectorFactory;
 import org.apache.ibatis.reflection.ReflectorFactory;
@@ -126,7 +127,7 @@ public class MybatisEnumTypeHandler<E extends Enum<?>> extends BaseTypeHandler<E
     public static Optional<String> findEnumValueFieldName(Class<?> clazz) {
     public static Optional<String> findEnumValueFieldName(Class<?> clazz) {
         if (clazz != null && clazz.isEnum()) {
         if (clazz != null && clazz.isEnum()) {
             String className = clazz.getName();
             String className = clazz.getName();
-            return Optional.ofNullable(TABLE_METHOD_OF_ENUM_TYPES.computeIfAbsent(className, key -> {
+            return Optional.ofNullable(Maps.computeIfAbsent(TABLE_METHOD_OF_ENUM_TYPES, className, key -> {
                 Optional<Field> optional = Arrays.stream(clazz.getDeclaredFields())
                 Optional<Field> optional = Arrays.stream(clazz.getDeclaredFields())
                     .filter(field -> field.isAnnotationPresent(EnumValue.class))
                     .filter(field -> field.isAnnotationPresent(EnumValue.class))
                     .findFirst();
                     .findFirst();

+ 2 - 2
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/inner/PaginationInnerInterceptor.java

@@ -172,7 +172,7 @@ public class PaginationInnerInterceptor implements InnerInterceptor {
             }
             }
             final Configuration configuration = ms.getConfiguration();
             final Configuration configuration = ms.getConfiguration();
             try {
             try {
-                return countMsCache.computeIfAbsent(countId, key -> configuration.getMappedStatement(key, false));
+                return Maps.computeIfAbsent(countMsCache, countId, key -> configuration.getMappedStatement(key, false));
             } catch (Exception e) {
             } catch (Exception e) {
                 logger.warn(String.format("can not find this countId: [\"%s\"]", countId));
                 logger.warn(String.format("can not find this countId: [\"%s\"]", countId));
             }
             }
@@ -183,7 +183,7 @@ public class PaginationInnerInterceptor implements InnerInterceptor {
     protected MappedStatement buildAutoCountMappedStatement(MappedStatement ms) {
     protected MappedStatement buildAutoCountMappedStatement(MappedStatement ms) {
         final String countId = ms.getId() + "_mpCount";
         final String countId = ms.getId() + "_mpCount";
         final Configuration configuration = ms.getConfiguration();
         final Configuration configuration = ms.getConfiguration();
-        return countMsCache.computeIfAbsent(countId, key -> {
+        return Maps.computeIfAbsent(countMsCache, countId, key -> {
             MappedStatement.Builder builder = new MappedStatement.Builder(configuration, key, ms.getSqlSource(), ms.getSqlCommandType());
             MappedStatement.Builder builder = new MappedStatement.Builder(configuration, key, ms.getSqlSource(), ms.getSqlCommandType());
             builder.resource(ms.getResource());
             builder.resource(ms.getResource());
             builder.fetchSize(ms.getFetchSize());
             builder.fetchSize(ms.getFetchSize());

+ 3 - 2
mybatis-plus-extension/src/main/java/com/baomidou/mybatisplus/extension/plugins/pagination/DialectFactory.java

@@ -19,6 +19,7 @@ import com.baomidou.mybatisplus.annotation.DbType;
 import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
 import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.core.toolkit.ClassUtils;
 import com.baomidou.mybatisplus.core.toolkit.ClassUtils;
+import com.baomidou.mybatisplus.core.toolkit.Maps;
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import com.baomidou.mybatisplus.extension.plugins.pagination.dialects.DialectRegistry;
 import com.baomidou.mybatisplus.extension.plugins.pagination.dialects.DialectRegistry;
 import com.baomidou.mybatisplus.extension.plugins.pagination.dialects.IDialect;
 import com.baomidou.mybatisplus.extension.plugins.pagination.dialects.IDialect;
@@ -71,7 +72,7 @@ public class DialectFactory {
     @Deprecated
     @Deprecated
     private static IDialect getDialect(DbType dbType, String dialectClazz) {
     private static IDialect getDialect(DbType dbType, String dialectClazz) {
         //这里需要注意一下,就的版本是把dbType和dialectClazz同时传进来的,所以会存在dbType是一定会有值,dialectClazz可能为空的情况,兼容需要先判断dialectClazz
         //这里需要注意一下,就的版本是把dbType和dialectClazz同时传进来的,所以会存在dbType是一定会有值,dialectClazz可能为空的情况,兼容需要先判断dialectClazz
-        return StringUtils.isBlank(dialectClazz) ? DIALECT_REGISTRY.getDialect(dbType) : DIALECT_CACHE.computeIfAbsent(dialectClazz, ClassUtils::newInstance);
+        return StringUtils.isBlank(dialectClazz) ? DIALECT_REGISTRY.getDialect(dbType) : Maps.computeIfAbsent(DIALECT_CACHE, dialectClazz, ClassUtils::newInstance);
     }
     }
 
 
     /**
     /**
@@ -82,7 +83,7 @@ public class DialectFactory {
      * @since 3.3.1
      * @since 3.3.1
      */
      */
     public static IDialect getDialect(String dialectClazz) {
     public static IDialect getDialect(String dialectClazz) {
-        return DIALECT_CACHE.computeIfAbsent(dialectClazz, ClassUtils::newInstance);
+        return Maps.computeIfAbsent(DIALECT_CACHE, dialectClazz, ClassUtils::newInstance);
     }
     }
     
     
     public static IDialect getDialect(DbType dbType) {
     public static IDialect getDialect(DbType dbType) {