Browse Source

Merge branch '3.0' into github3.0

hubin 2 years ago
parent
commit
d95416c298
17 changed files with 692 additions and 66 deletions
  1. 8 2
      mybatis-plus-annotation/src/main/java/com/baomidou/mybatisplus/annotation/KeySequence.java
  2. 13 2
      mybatis-plus-boot-starter/src/main/java/com/baomidou/mybatisplus/autoconfigure/MybatisPlusAutoConfiguration.java
  3. 5 0
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/config/GlobalConfig.java
  4. 84 0
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/handlers/AnnotationHandler.java
  5. 6 1
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/handlers/MybatisEnumTypeHandler.java
  6. 38 21
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/metadata/TableFieldInfo.java
  7. 116 33
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/metadata/TableInfoHelper.java
  8. 5 0
      mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/toolkit/GlobalConfigUtils.java
  9. 2 2
      mybatis-plus-core/src/test/java/com/baomidou/mybatisplus/test/metadata/TableInfoHelperTest.java
  10. 16 5
      mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/builder/Entity.java
  11. 40 0
      mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/CustomFillTest.java
  12. 296 0
      mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/customfill/CustomFillConfig.java
  13. 17 0
      mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/customfill/annotation/InsertUpdateFill.java
  14. 8 0
      mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/customfill/mapper/TestModelMapper.java
  15. 18 0
      mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/customfill/model/TestModel.java
  16. 6 0
      mybatis-plus/src/test/resources/customfilltest/init.ddl.sql
  17. 14 0
      mybatis-plus/src/test/resources/h2/spring-custom-fill-test-h2.xml

+ 8 - 2
mybatis-plus-annotation/src/main/java/com/baomidou/mybatisplus/annotation/KeySequence.java

@@ -15,7 +15,13 @@
  */
 package com.baomidou.mybatisplus.annotation;
 
-import java.lang.annotation.*;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
 
 /**
  * 序列主键策略
@@ -27,7 +33,7 @@ import java.lang.annotation.*;
 @Documented
 @Inherited
 @Retention(RetentionPolicy.RUNTIME)
-@Target(ElementType.TYPE)
+@Target({ElementType.TYPE, ElementType.ANNOTATION_TYPE})
 public @interface KeySequence {
 
     /**

+ 13 - 2
mybatis-plus-boot-starter/src/main/java/com/baomidou/mybatisplus/autoconfigure/MybatisPlusAutoConfiguration.java

@@ -18,6 +18,7 @@ package com.baomidou.mybatisplus.autoconfigure;
 
 import com.baomidou.mybatisplus.core.MybatisConfiguration;
 import com.baomidou.mybatisplus.core.config.GlobalConfig;
+import com.baomidou.mybatisplus.core.handlers.AnnotationHandler;
 import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
 import com.baomidou.mybatisplus.core.handlers.PostInitTableInfoHandler;
 import com.baomidou.mybatisplus.core.incrementer.IKeyGenerator;
@@ -41,7 +42,11 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.BeanWrapper;
 import org.springframework.beans.BeanWrapperImpl;
-import org.springframework.beans.factory.*;
+import org.springframework.beans.factory.BeanFactory;
+import org.springframework.beans.factory.BeanFactoryAware;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.ListableBeanFactory;
+import org.springframework.beans.factory.ObjectProvider;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.config.BeanDefinition;
 import org.springframework.beans.factory.support.BeanDefinitionBuilder;
@@ -72,7 +77,11 @@ import org.springframework.util.StringUtils;
 
 import javax.sql.DataSource;
 import java.beans.PropertyDescriptor;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
 import java.util.function.Consumer;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
@@ -211,6 +220,8 @@ public class MybatisPlusAutoConfiguration implements InitializingBean {
         GlobalConfig globalConfig = this.properties.getGlobalConfig();
         // TODO 注入填充器
         this.getBeanThen(MetaObjectHandler.class, globalConfig::setMetaObjectHandler);
+        // TODO 注入注解控制器
+        this.getBeanThen(AnnotationHandler.class, globalConfig::setAnnotationHandler);
         // TODO 注入参与器
         this.getBeanThen(PostInitTableInfoHandler.class, globalConfig::setPostInitTableInfoHandler);
         // TODO 注入主键生成器

+ 5 - 0
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/config/GlobalConfig.java

@@ -18,6 +18,7 @@ package com.baomidou.mybatisplus.core.config;
 import com.baomidou.mybatisplus.annotation.FieldStrategy;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.core.handlers.AnnotationHandler;
 import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
 import com.baomidou.mybatisplus.core.handlers.PostInitTableInfoHandler;
 import com.baomidou.mybatisplus.core.incrementer.IKeyGenerator;
@@ -76,6 +77,10 @@ public class GlobalConfig implements Serializable {
      * 元对象字段填充控制器
      */
     private MetaObjectHandler metaObjectHandler;
+    /**
+     * 注解控制器
+     */
+    private AnnotationHandler annotationHandler = new AnnotationHandler(){};
     /**
      * 参与 TableInfo 的初始化
      */

+ 84 - 0
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/handlers/AnnotationHandler.java

@@ -0,0 +1,84 @@
+package com.baomidou.mybatisplus.core.handlers;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+
+/**
+ * @author 唐振超
+ * @since 2023-02-25
+ */
+public interface AnnotationHandler {
+
+    /**
+     * 从类上获取注解
+     *
+     * @param beanClass       类的class
+     * @param annotationClass 要获取的注解class
+     * @param <T>             具体注解
+     * @return 注解
+     */
+    default <T extends Annotation> T getAnnotation(Class<?> beanClass, Class<T> annotationClass) {
+        return beanClass.getAnnotation(annotationClass);
+    }
+
+    /**
+     * 判断类上是否存在注解
+     *
+     * @param beanClass       类的class
+     * @param annotationClass 要获取的注解class
+     * @param <T>             具体注解
+     * @return 是否包含该注解
+     */
+    default <T extends Annotation> boolean isAnnotationPresent(Class<?> beanClass, Class<T> annotationClass) {
+        return beanClass.isAnnotationPresent(annotationClass);
+    }
+
+    /**
+     * 从字段上获取注解
+     *
+     * @param field           字段
+     * @param annotationClass 要获取的注解class
+     * @param <T>             具体注解
+     * @return 注解
+     */
+    default <T extends Annotation> T getAnnotation(Field field, Class<T> annotationClass) {
+        return field.getAnnotation(annotationClass);
+    }
+
+    /**
+     * 判断字段上是否存在注解
+     *
+     * @param field           字段
+     * @param annotationClass 要获取的注解class
+     * @param <T>             具体注解
+     * @return 是否包含该注解
+     */
+    default <T extends Annotation> boolean isAnnotationPresent(Field field, Class<T> annotationClass) {
+        return field.isAnnotationPresent(annotationClass);
+    }
+
+    /**
+     * 从方法上获取注解
+     *
+     * @param method          方法
+     * @param annotationClass 要获取的注解class
+     * @param <T>             具体注解
+     * @return 注解
+     */
+    default <T extends Annotation> T getAnnotation(Method method, Class<T> annotationClass) {
+        return method.getAnnotation(annotationClass);
+    }
+
+    /**
+     * 判断方法上是否存在注解
+     *
+     * @param method           方法
+     * @param annotationClass 要获取的注解class
+     * @param <T>             具体注解
+     * @return 是否包含该注解
+     */
+    default <T extends Annotation> boolean isAnnotationPresent(Method method, Class<T> annotationClass) {
+        return method.isAnnotationPresent(annotationClass);
+    }
+}

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

@@ -17,8 +17,11 @@ package com.baomidou.mybatisplus.core.handlers;
 
 import com.baomidou.mybatisplus.annotation.EnumValue;
 import com.baomidou.mybatisplus.annotation.IEnum;
+import com.baomidou.mybatisplus.core.metadata.TableInfo;
+import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
 import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
+import com.baomidou.mybatisplus.core.toolkit.GlobalConfigUtils;
 import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import org.apache.ibatis.reflection.DefaultReflectorFactory;
@@ -87,7 +90,9 @@ public class MybatisEnumTypeHandler<E extends Enum<E>> extends BaseTypeHandler<E
     }
 
     private static Optional<Field> findEnumValueAnnotationField(Class<?> clazz) {
-        return Arrays.stream(clazz.getDeclaredFields()).filter(field -> field.isAnnotationPresent(EnumValue.class)).findFirst();
+        TableInfo tableInfo = TableInfoHelper.getTableInfo(clazz);
+        AnnotationHandler annotationHandler = GlobalConfigUtils.getGlobalConfig(tableInfo.getConfiguration()).getAnnotationHandler();
+        return Arrays.stream(clazz.getDeclaredFields()).filter(field -> annotationHandler.isAnnotationPresent(field, EnumValue.class)).findFirst();
     }
 
     /**

+ 38 - 21
mybatis-plus-core/src/main/java/com/baomidou/mybatisplus/core/metadata/TableFieldInfo.java

@@ -15,16 +15,30 @@
  */
 package com.baomidou.mybatisplus.core.metadata;
 
-import com.baomidou.mybatisplus.annotation.*;
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.FieldStrategy;
+import com.baomidou.mybatisplus.annotation.OrderBy;
+import com.baomidou.mybatisplus.annotation.SqlCondition;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.Version;
 import com.baomidou.mybatisplus.core.config.GlobalConfig;
 import com.baomidou.mybatisplus.core.toolkit.Constants;
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils;
-import lombok.*;
+import lombok.AccessLevel;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
 import org.apache.ibatis.mapping.ResultMapping;
 import org.apache.ibatis.reflection.Reflector;
 import org.apache.ibatis.session.Configuration;
-import org.apache.ibatis.type.*;
+import org.apache.ibatis.type.JdbcType;
+import org.apache.ibatis.type.TypeAliasRegistry;
+import org.apache.ibatis.type.TypeHandler;
+import org.apache.ibatis.type.TypeHandlerRegistry;
+import org.apache.ibatis.type.UnknownTypeHandler;
 
 import java.lang.reflect.Field;
 import java.util.Map;
@@ -179,12 +193,12 @@ public class TableFieldInfo implements Constants {
      * 全新的 存在 TableField 注解时使用的构造函数
      */
     @SuppressWarnings({"unchecked", "rawtypes"})
-    public TableFieldInfo(GlobalConfig.DbConfig dbConfig, TableInfo tableInfo, Field field, TableField tableField,
+    public TableFieldInfo(GlobalConfig globalConfig, TableInfo tableInfo, Field field, TableField tableField,
                           Reflector reflector, boolean existTableLogic, boolean isOrderBy) {
-        this(dbConfig, tableInfo, field, tableField, reflector, existTableLogic);
+        this(globalConfig, tableInfo, field, tableField, reflector, existTableLogic);
         this.isOrderBy = isOrderBy;
         if (isOrderBy) {
-            initOrderBy(field);
+            initOrderBy(globalConfig.getAnnotationHandler().getAnnotation(field, OrderBy.class));
         }
     }
 
@@ -192,11 +206,13 @@ public class TableFieldInfo implements Constants {
      * 全新的 存在 TableField 注解时使用的构造函数
      */
     @SuppressWarnings({"unchecked", "rawtypes"})
-    public TableFieldInfo(GlobalConfig.DbConfig dbConfig, TableInfo tableInfo, Field field, TableField tableField,
+    public TableFieldInfo(GlobalConfig globalConfig, TableInfo tableInfo, Field field, TableField tableField,
                           Reflector reflector, boolean existTableLogic) {
+
+        GlobalConfig.DbConfig dbConfig = globalConfig.getDbConfig();
         field.setAccessible(true);
         this.field = field;
-        this.version = field.getAnnotation(Version.class) != null;
+        this.version = globalConfig.getAnnotationHandler().isAnnotationPresent(field, Version.class);
         this.property = field.getName();
         this.propertyType = reflector.getGetterType(this.property);
         this.isPrimitive = this.propertyType.isPrimitive();
@@ -244,7 +260,7 @@ public class TableFieldInfo implements Constants {
         this.el = el;
         int index = el.indexOf(COMMA);
         this.mapping = index > 0 ? el.substring(++index) : null;
-        this.initLogicDelete(dbConfig, field, existTableLogic);
+        this.initLogicDelete(globalConfig, field, existTableLogic);
 
         String column = tableField.value();
         if (StringUtils.isBlank(column)) {
@@ -306,33 +322,34 @@ public class TableFieldInfo implements Constants {
     /**
      * 不存在 TableField 注解时, 使用的构造函数
      */
-    public TableFieldInfo(GlobalConfig.DbConfig dbConfig, TableInfo tableInfo, Field field, Reflector reflector,
+    public TableFieldInfo(GlobalConfig globalConfig, TableInfo tableInfo, Field field, Reflector reflector,
                           boolean existTableLogic, boolean isOrderBy) {
-        this(dbConfig, tableInfo, field, reflector, existTableLogic);
+        this(globalConfig, tableInfo, field, reflector, existTableLogic);
         this.isOrderBy = isOrderBy;
         if (isOrderBy) {
-            initOrderBy(field);
+            initOrderBy(globalConfig.getAnnotationHandler().getAnnotation(field, OrderBy.class));
         }
     }
 
     /**
      * 不存在 TableField 注解时, 使用的构造函数
      */
-    public TableFieldInfo(GlobalConfig.DbConfig dbConfig, TableInfo tableInfo, Field field, Reflector reflector,
+    public TableFieldInfo(GlobalConfig globalConfig, TableInfo tableInfo, Field field, Reflector reflector,
                           boolean existTableLogic) {
         field.setAccessible(true);
         this.field = field;
-        this.version = field.getAnnotation(Version.class) != null;
+        this.version = globalConfig.getAnnotationHandler().isAnnotationPresent(field, Version.class);
         this.property = field.getName();
         this.propertyType = reflector.getGetterType(this.property);
         this.isPrimitive = this.propertyType.isPrimitive();
         this.isCharSequence = StringUtils.isCharSequence(this.propertyType);
         this.el = this.property;
         this.mapping = null;
+        GlobalConfig.DbConfig dbConfig = globalConfig.getDbConfig();
         this.insertStrategy = dbConfig.getInsertStrategy();
         this.updateStrategy = dbConfig.getUpdateStrategy();
         this.whereStrategy = dbConfig.getWhereStrategy();
-        this.initLogicDelete(dbConfig, field, existTableLogic);
+        this.initLogicDelete(globalConfig, field, existTableLogic);
 
         String column = this.property;
         if (tableInfo.isUnderCamel()) {
@@ -366,10 +383,9 @@ public class TableFieldInfo implements Constants {
     /**
      * 排序初始化
      *
-     * @param field 字段
+     * @param orderBy 排序注解
      */
-    private void initOrderBy(Field field) {
-        OrderBy orderBy = field.getAnnotation(OrderBy.class);
+    private void initOrderBy(OrderBy orderBy) {
         if (null != orderBy) {
             this.isOrderBy = true;
             this.orderBySort = orderBy.sort();
@@ -386,12 +402,13 @@ public class TableFieldInfo implements Constants {
     /**
      * 逻辑删除初始化
      *
-     * @param dbConfig 数据库全局配置
+     * @param globalConfig 全局配置
      * @param field    字段属性对象
      */
-    private void initLogicDelete(GlobalConfig.DbConfig dbConfig, Field field, boolean existTableLogic) {
+    private void initLogicDelete(GlobalConfig globalConfig, Field field, boolean existTableLogic) {
+        GlobalConfig.DbConfig dbConfig = globalConfig.getDbConfig();
         /* 获取注解属性,逻辑处理字段 */
-        TableLogic tableLogic = field.getAnnotation(TableLogic.class);
+        TableLogic tableLogic = globalConfig.getAnnotationHandler().getAnnotation(field, TableLogic.class);
         if (null != tableLogic) {
             if (StringUtils.isNotBlank(tableLogic.value())) {
                 this.logicNotDeleteValue = tableLogic.value();

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

@@ -15,11 +15,26 @@
  */
 package com.baomidou.mybatisplus.core.metadata;
 
-import com.baomidou.mybatisplus.annotation.*;
+import com.baomidou.mybatisplus.annotation.DbType;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.OrderBy;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
 import com.baomidou.mybatisplus.core.config.GlobalConfig;
+import com.baomidou.mybatisplus.core.handlers.AnnotationHandler;
 import com.baomidou.mybatisplus.core.handlers.PostInitTableInfoHandler;
 import com.baomidou.mybatisplus.core.incrementer.IKeyGenerator;
-import com.baomidou.mybatisplus.core.toolkit.*;
+import com.baomidou.mybatisplus.core.toolkit.ClassUtils;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
+import com.baomidou.mybatisplus.core.toolkit.GlobalConfigUtils;
+import com.baomidou.mybatisplus.core.toolkit.LambdaUtils;
+import com.baomidou.mybatisplus.core.toolkit.ReflectionKit;
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import org.apache.ibatis.builder.MapperBuilderAssistant;
 import org.apache.ibatis.builder.StaticSqlSource;
 import org.apache.ibatis.executor.keygen.KeyGenerator;
@@ -34,7 +49,12 @@ import org.apache.ibatis.session.Configuration;
 import org.apache.ibatis.type.SimpleTypeRegistry;
 
 import java.lang.reflect.Field;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 
 import static java.util.stream.Collectors.toList;
@@ -139,7 +159,7 @@ public class TableInfoHelper {
      * @param clazz 反射实体类
      * @return 数据库表反射信息
      */
-    public synchronized static TableInfo initTableInfo(MapperBuilderAssistant builderAssistant, Class<?> clazz) {
+    public static synchronized TableInfo initTableInfo(MapperBuilderAssistant builderAssistant, Class<?> clazz) {
         TableInfo targetTableInfo = TABLE_INFO_CACHE.get(clazz);
         final Configuration configuration = builderAssistant.getConfiguration();
         if (targetTableInfo != null) {
@@ -161,7 +181,7 @@ public class TableInfoHelper {
      * @param clazz 反射实体类
      * @return 数据库表反射信息
      */
-    private synchronized static TableInfo initTableInfo(Configuration configuration, String currentNamespace, Class<?> clazz) {
+    private static synchronized TableInfo initTableInfo(Configuration configuration, String currentNamespace, Class<?> clazz) {
         /* 没有获取到缓存信息,则初始化 */
         TableInfo tableInfo = new TableInfo(configuration, clazz);
         tableInfo.setCurrentNamespace(currentNamespace);
@@ -199,7 +219,8 @@ public class TableInfoHelper {
     private static String[] initTableName(Class<?> clazz, GlobalConfig globalConfig, TableInfo tableInfo) {
         /* 数据库全局配置 */
         GlobalConfig.DbConfig dbConfig = globalConfig.getDbConfig();
-        TableName table = clazz.getAnnotation(TableName.class);
+        AnnotationHandler annotationHandler = globalConfig.getAnnotationHandler();
+        TableName table = annotationHandler.getAnnotation(clazz, TableName.class);
 
         String tableName = clazz.getSimpleName();
         String tablePrefix = dbConfig.getTablePrefix();
@@ -241,7 +262,7 @@ public class TableInfoHelper {
 
         /* 开启了自定义 KEY 生成器 */
         if (CollectionUtils.isNotEmpty(dbConfig.getKeyGenerators())) {
-            tableInfo.setKeySequence(clazz.getAnnotation(KeySequence.class));
+            tableInfo.setKeySequence(annotationHandler.getAnnotation(clazz, KeySequence.class));
         }
         return excludeProperty;
     }
@@ -279,17 +300,16 @@ public class TableInfoHelper {
      * @param tableInfo    数据库表反射信息
      */
     private static void initTableFields(Configuration configuration, Class<?> clazz, GlobalConfig globalConfig, TableInfo tableInfo, List<String> excludeProperty) {
-        /* 数据库全局配置 */
-        GlobalConfig.DbConfig dbConfig = globalConfig.getDbConfig();
+        AnnotationHandler annotationHandler = globalConfig.getAnnotationHandler();
         PostInitTableInfoHandler postInitTableInfoHandler = globalConfig.getPostInitTableInfoHandler();
         Reflector reflector = tableInfo.getReflector();
-        List<Field> list = getAllFields(clazz);
+        List<Field> list = getAllFields(clazz, annotationHandler);
         // 标记是否读取到主键
         boolean isReadPK = false;
         // 是否存在 @TableId 注解
-        boolean existTableId = isExistTableId(list);
+        boolean existTableId = isExistTableId(list, annotationHandler);
         // 是否存在 @TableLogic 注解
-        boolean existTableLogic = isExistTableLogic(list);
+        boolean existTableLogic = isExistTableLogic(list, annotationHandler);
 
         List<TableFieldInfo> fieldList = new ArrayList<>(list.size());
         for (Field field : list) {
@@ -298,43 +318,42 @@ public class TableInfoHelper {
             }
 
             boolean isPK = false;
-            boolean isOrderBy = field.getAnnotation(OrderBy.class) != null;
+            boolean isOrderBy = annotationHandler.getAnnotation(field, OrderBy.class) != null;
 
             /* 主键ID 初始化 */
             if (existTableId) {
-                TableId tableId = field.getAnnotation(TableId.class);
+                TableId tableId = annotationHandler.getAnnotation(field, TableId.class);
                 if (tableId != null) {
                     if (isReadPK) {
                         throw ExceptionUtils.mpe("@TableId can't more than one in Class: \"%s\".", clazz.getName());
                     }
 
-                    initTableIdWithAnnotation(dbConfig, tableInfo, field, tableId);
+                    initTableIdWithAnnotation(globalConfig, tableInfo, field, tableId);
                     isPK = isReadPK = true;
                 }
             } else if (!isReadPK) {
-                isPK = isReadPK = initTableIdWithoutAnnotation(dbConfig, tableInfo, field);
-
+                isPK = isReadPK = initTableIdWithoutAnnotation(globalConfig, tableInfo, field);
             }
 
             if (isPK) {
                 if (isOrderBy) {
-                    tableInfo.getOrderByFields().add(new TableFieldInfo(dbConfig, tableInfo, field, reflector, existTableLogic, true));
+                    tableInfo.getOrderByFields().add(new TableFieldInfo(globalConfig, tableInfo, field, reflector, existTableLogic, true));
                 }
                 continue;
             }
 
-            final TableField tableField = field.getAnnotation(TableField.class);
+            final TableField tableField = annotationHandler.getAnnotation(field, TableField.class);
 
             /* 有 @TableField 注解的字段初始化 */
             if (tableField != null) {
-                TableFieldInfo tableFieldInfo = new TableFieldInfo(dbConfig, tableInfo, field, tableField, reflector, existTableLogic, isOrderBy);
+                TableFieldInfo tableFieldInfo = new TableFieldInfo(globalConfig, tableInfo, field, tableField, reflector, existTableLogic, isOrderBy);
                 fieldList.add(tableFieldInfo);
                 postInitTableInfoHandler.postFieldInfo(tableFieldInfo, configuration);
                 continue;
             }
 
             /* 无 @TableField  注解的字段初始化 */
-            TableFieldInfo tableFieldInfo = new TableFieldInfo(dbConfig, tableInfo, field, reflector, existTableLogic, isOrderBy);
+            TableFieldInfo tableFieldInfo = new TableFieldInfo(globalConfig, tableInfo, field, reflector, existTableLogic, isOrderBy);
             fieldList.add(tableFieldInfo);
             postInitTableInfoHandler.postFieldInfo(tableFieldInfo, configuration);
         }
@@ -353,11 +372,41 @@ public class TableInfoHelper {
      * 判断主键注解是否存在
      * </p>
      *
+     * @param clazz 实体类
      * @param list 字段列表
      * @return true 为存在 {@link TableId} 注解;
      */
-    public static boolean isExistTableId(List<Field> list) {
-        return list.stream().anyMatch(field -> field.isAnnotationPresent(TableId.class));
+    public static boolean isExistTableId(Class<?> clazz, List<Field> list) {
+        TableInfo tableInfo = TableInfoHelper.getTableInfo(clazz);
+        AnnotationHandler annotationHandler = GlobalConfigUtils.getGlobalConfig(tableInfo.getConfiguration()).getAnnotationHandler();
+        return isExistTableId(list, annotationHandler);
+    }
+
+    /**
+     * <p>
+     * 判断主键注解是否存在
+     * </p>
+     *
+     * @param list 字段列表
+     * @return true 为存在 {@link TableId} 注解;
+     */
+    public static boolean isExistTableId(List<Field> list, AnnotationHandler annotationHandler) {
+        return list.stream().anyMatch(field -> annotationHandler.isAnnotationPresent(field, TableId.class));
+    }
+
+    /**
+     * <p>
+     * 判断逻辑删除注解是否存在
+     * </p>
+     *
+     * @param clazz 实体类
+     * @param list 字段列表
+     * @return true 为存在 {@link TableLogic} 注解;
+     */
+    public static boolean isExistTableLogic(Class<?> clazz, List<Field> list) {
+        TableInfo tableInfo = TableInfoHelper.getTableInfo(clazz);
+        AnnotationHandler annotationHandler = GlobalConfigUtils.getGlobalConfig(tableInfo.getConfiguration()).getAnnotationHandler();
+        return isExistTableLogic(list, annotationHandler);
     }
 
     /**
@@ -368,8 +417,8 @@ public class TableInfoHelper {
      * @param list 字段列表
      * @return true 为存在 {@link TableLogic} 注解;
      */
-    public static boolean isExistTableLogic(List<Field> list) {
-        return list.stream().anyMatch(field -> field.isAnnotationPresent(TableLogic.class));
+    public static boolean isExistTableLogic(List<Field> list, AnnotationHandler annotationHandler) {
+        return list.stream().anyMatch(field -> annotationHandler.isAnnotationPresent(field, TableLogic.class));
     }
 
     /**
@@ -377,11 +426,27 @@ public class TableInfoHelper {
      * 判断排序注解是否存在
      * </p>
      *
+     * @param clazz 实体类
      * @param list 字段列表
      * @return true 为存在 {@link OrderBy} 注解;
      */
-    public static boolean isExistOrderBy(List<Field> list) {
-        return list.stream().anyMatch(field -> field.isAnnotationPresent(OrderBy.class));
+    public static boolean isExistOrderBy(Class<?> clazz, List<Field> list) {
+        TableInfo tableInfo = TableInfoHelper.getTableInfo(clazz);
+        AnnotationHandler annotationHandler = GlobalConfigUtils.getGlobalConfig(tableInfo.getConfiguration()).getAnnotationHandler();
+        return isExistOrderBy(list, annotationHandler);
+    }
+
+    /**
+     * <p>
+     * 判断排序注解是否存在
+     * </p>
+     *
+     * @param list 字段列表
+     * @param annotationHandler 注解处理类
+     * @return true 为存在 {@link OrderBy} 注解;
+     */
+    public static boolean isExistOrderBy(List<Field> list, AnnotationHandler annotationHandler) {
+        return list.stream().anyMatch(field -> annotationHandler.isAnnotationPresent(field, OrderBy.class));
     }
 
     /**
@@ -389,15 +454,16 @@ public class TableInfoHelper {
      * 主键属性初始化
      * </p>
      *
-     * @param dbConfig  全局配置信息
+     * @param globalConfig  全局配置信息
      * @param tableInfo 表信息
      * @param field     字段
      * @param tableId   注解
      */
-    private static void initTableIdWithAnnotation(GlobalConfig.DbConfig dbConfig, TableInfo tableInfo, Field field, TableId tableId) {
+    private static void initTableIdWithAnnotation(GlobalConfig globalConfig, TableInfo tableInfo, Field field, TableId tableId) {
+        GlobalConfig.DbConfig dbConfig = globalConfig.getDbConfig();
         boolean underCamel = tableInfo.isUnderCamel();
         final String property = field.getName();
-        if (field.getAnnotation(TableField.class) != null) {
+        if (globalConfig.getAnnotationHandler().isAnnotationPresent(field, TableField.class)) {
             logger.warn(String.format("This \"%s\" is the table primary key by @TableId annotation in Class: \"%s\",So @TableField annotation will not work!",
                 property, tableInfo.getEntityType().getName()));
         }
@@ -445,14 +511,16 @@ public class TableInfoHelper {
      * 主键属性初始化
      * </p>
      *
+     * @param globalConfig 全局配置
      * @param tableInfo 表信息
      * @param field     字段
      * @return true 继续下一个属性判断,返回 continue;
      */
-    private static boolean initTableIdWithoutAnnotation(GlobalConfig.DbConfig dbConfig, TableInfo tableInfo, Field field) {
+    private static boolean initTableIdWithoutAnnotation(GlobalConfig globalConfig, TableInfo tableInfo, Field field) {
+        GlobalConfig.DbConfig dbConfig = globalConfig.getDbConfig();
         final String property = field.getName();
         if (DEFAULT_ID_NAME.equalsIgnoreCase(property)) {
-            if (field.getAnnotation(TableField.class) != null) {
+            if (globalConfig.getAnnotationHandler().isAnnotationPresent(field, TableField.class)) {
                 logger.warn(String.format("This \"%s\" is the table primary key by default name for `id` in Class: \"%s\",So @TableField will not work!",
                     property, tableInfo.getEntityType().getName()));
             }
@@ -512,11 +580,26 @@ public class TableInfoHelper {
      * @return 属性集合
      */
     public static List<Field> getAllFields(Class<?> clazz) {
+        TableInfo tableInfo = TableInfoHelper.getTableInfo(clazz);
+        AnnotationHandler annotationHandler = GlobalConfigUtils.getGlobalConfig(tableInfo.getConfiguration()).getAnnotationHandler();
+        return getAllFields(clazz, annotationHandler);
+    }
+
+    /**
+     * <p>
+     * 获取该类的所有属性列表
+     * </p>
+     *
+     * @param clazz             反射类
+     * @param annotationHandler 注解处理类
+     * @return 属性集合
+     */
+    public static List<Field> getAllFields(Class<?> clazz, AnnotationHandler annotationHandler) {
         List<Field> fieldList = ReflectionKit.getFieldList(ClassUtils.getUserClass(clazz));
         return fieldList.stream()
             .filter(field -> {
                 /* 过滤注解非表字段属性 */
-                TableField tableField = field.getAnnotation(TableField.class);
+                TableField tableField = annotationHandler.getAnnotation(field, TableField.class);
                 return (tableField == null || tableField.exist());
             }).collect(toList());
     }

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

@@ -17,6 +17,7 @@ package com.baomidou.mybatisplus.core.toolkit;
 
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.core.config.GlobalConfig;
+import com.baomidou.mybatisplus.core.handlers.AnnotationHandler;
 import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
 import com.baomidou.mybatisplus.core.incrementer.IKeyGenerator;
 import com.baomidou.mybatisplus.core.injector.ISqlInjector;
@@ -108,6 +109,10 @@ public class GlobalConfigUtils {
         return Optional.ofNullable(getGlobalConfig(configuration).getMetaObjectHandler());
     }
 
+    public static Optional<AnnotationHandler> getAnnotationHandler(Configuration configuration) {
+        return Optional.ofNullable(getGlobalConfig(configuration).getAnnotationHandler());
+    }
+
     public static Class<?> getSuperMapperClass(Configuration configuration) {
         return getGlobalConfig(configuration).getSuperMapperClass();
     }

+ 2 - 2
mybatis-plus-core/src/test/java/com/baomidou/mybatisplus/test/metadata/TableInfoHelperTest.java

@@ -74,8 +74,8 @@ class TableInfoHelperTest {
 
     @Test
     void testIsExistTableId() {
-        Assertions.assertThat(TableInfoHelper.isExistTableId(Arrays.asList(ModelOne.class.getDeclaredFields()))).isTrue();
-        assertThat(TableInfoHelper.isExistTableId(Arrays.asList(ModelTwo.class.getDeclaredFields()))).isFalse();
+        Assertions.assertThat(TableInfoHelper.isExistTableId(ModelOne.class, Arrays.asList(ModelOne.class.getDeclaredFields()))).isTrue();
+        assertThat(TableInfoHelper.isExistTableId(ModelTwo.class, Arrays.asList(ModelTwo.class.getDeclaredFields()))).isFalse();
     }
 
     @Test

+ 16 - 5
mybatis-plus-generator/src/main/java/com/baomidou/mybatisplus/generator/config/builder/Entity.java

@@ -18,7 +18,9 @@ package com.baomidou.mybatisplus.generator.config.builder;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.core.handlers.AnnotationHandler;
 import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
+import com.baomidou.mybatisplus.core.toolkit.GlobalConfigUtils;
 import com.baomidou.mybatisplus.core.toolkit.StringUtils;
 import com.baomidou.mybatisplus.generator.IFill;
 import com.baomidou.mybatisplus.generator.ITemplate;
@@ -34,7 +36,14 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import java.lang.reflect.Field;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
 import java.util.stream.Collectors;
 
 /**
@@ -45,7 +54,7 @@ import java.util.stream.Collectors;
  */
 public class Entity implements ITemplate {
 
-    private final static Logger LOGGER = LoggerFactory.getLogger(Entity.class);
+    private static final Logger LOGGER = LoggerFactory.getLogger(Entity.class);
 
     private Entity() {
     }
@@ -187,13 +196,15 @@ public class Entity implements ITemplate {
      * @param clazz 实体父类 Class
      */
     public void convertSuperEntityColumns(Class<?> clazz) {
-        List<Field> fields = TableInfoHelper.getAllFields(clazz);
+        com.baomidou.mybatisplus.core.metadata.TableInfo tableInfo = TableInfoHelper.getTableInfo(clazz);
+        AnnotationHandler annotationHandler = GlobalConfigUtils.getGlobalConfig(tableInfo.getConfiguration()).getAnnotationHandler();
+        List<Field> fields = TableInfoHelper.getAllFields(clazz, annotationHandler);
         this.superEntityColumns.addAll(fields.stream().map(field -> {
-            TableId tableId = field.getAnnotation(TableId.class);
+            TableId tableId = annotationHandler.getAnnotation(field, TableId.class);
             if (tableId != null && StringUtils.isNotBlank(tableId.value())) {
                 return tableId.value();
             }
-            TableField tableField = field.getAnnotation(TableField.class);
+            TableField tableField = annotationHandler.getAnnotation(field, TableField.class);
             if (tableField != null && StringUtils.isNotBlank(tableField.value())) {
                 return tableField.value();
             }

+ 40 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/CustomFillTest.java

@@ -0,0 +1,40 @@
+package com.baomidou.mybatisplus.test.h2;
+
+import com.baomidou.mybatisplus.core.MybatisConfiguration;
+import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
+import com.baomidou.mybatisplus.test.h2.customfill.mapper.TestModelMapper;
+import com.baomidou.mybatisplus.test.h2.customfill.model.TestModel;
+import org.apache.ibatis.builder.MapperBuilderAssistant;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestMethodOrder;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+import javax.annotation.Resource;
+
+@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
+@ExtendWith(SpringExtension.class)
+@ContextConfiguration(locations = {"classpath:h2/spring-custom-fill-test-h2.xml"})
+public class CustomFillTest {
+
+    @Resource
+    private TestModelMapper testModelMapper;
+
+    @BeforeAll
+    public static void before(){
+        TableInfoHelper.initTableInfo(new MapperBuilderAssistant(new MybatisConfiguration(), ""), TestModel.class);
+    }
+
+    @Test
+    public void testInsert() {
+
+        TestModel testModel = new TestModel();
+        testModelMapper.insert(testModel);
+        Assertions.assertNotNull(testModel.getA());
+        Assertions.assertNotNull(testModel.getB());
+    }
+}

+ 296 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/customfill/CustomFillConfig.java

@@ -0,0 +1,296 @@
+package com.baomidou.mybatisplus.test.h2.customfill;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.FieldStrategy;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.core.MybatisConfiguration;
+import com.baomidou.mybatisplus.core.config.GlobalConfig;
+import com.baomidou.mybatisplus.core.handlers.AnnotationHandler;
+import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
+import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
+import com.baomidou.mybatisplus.core.toolkit.GlobalConfigUtils;
+import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
+import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
+import com.baomidou.mybatisplus.test.h2.customfill.annotation.InsertUpdateFill;
+import org.apache.ibatis.reflection.MetaObject;
+import org.apache.ibatis.session.ExecutorType;
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.apache.ibatis.type.EnumOrdinalTypeHandler;
+import org.apache.ibatis.type.JdbcType;
+import org.apache.ibatis.type.TypeHandler;
+import org.apache.ibatis.type.UnknownTypeHandler;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import javax.sql.DataSource;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+@Configuration
+@MapperScan("com.baomidou.mybatisplus.test.h2.customfill.mapper")
+public class CustomFillConfig {
+
+    @Bean
+    public SqlSessionFactory sqlSessionFactory(DataSource dataSource) throws Exception {
+        MybatisSqlSessionFactoryBean sqlSessionFactory = new MybatisSqlSessionFactoryBean();
+        sqlSessionFactory.setDataSource(dataSource);
+        MybatisConfiguration configuration = new MybatisConfiguration();
+        configuration.setJdbcTypeForNull(JdbcType.NULL);
+        configuration.setMapUnderscoreToCamelCase(true);
+        configuration.setDefaultExecutorType(ExecutorType.REUSE);
+        configuration.setDefaultEnumTypeHandler(EnumOrdinalTypeHandler.class);
+        sqlSessionFactory.setConfiguration(configuration);
+        GlobalConfig globalConfig = new GlobalConfig();
+        globalConfig.setMetaObjectHandler(metaObjectHandler());
+        globalConfig.setAnnotationHandler(annotationHandler());
+        sqlSessionFactory.setGlobalConfig(globalConfig);
+
+        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
+        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor());
+        sqlSessionFactory.setPlugins(mybatisPlusInterceptor);
+
+        return sqlSessionFactory.getObject();
+    }
+
+    @Bean
+    public MetaObjectHandler metaObjectHandler() {
+        return new MetaObjectHandler() {
+            @Override
+            public void insertFill(MetaObject metaObject) {
+                Object object = metaObject.getOriginalObject();
+                Class<?> clazz = object.getClass();
+
+                Field[] declaredFields = clazz.getDeclaredFields();
+                List<Field> fieldList = Arrays.stream(declaredFields)
+                    .filter(field -> metaObject.hasSetter(field.getName()))
+                    .filter(field -> {
+                        AnnotationHandler annotationHandler = GlobalConfigUtils.getGlobalConfig(TableInfoHelper.getTableInfo(clazz).getConfiguration()).getAnnotationHandler();
+                        return annotationHandler.isAnnotationPresent(field, TableField.class);
+                    })
+                    .collect(Collectors.toList());
+
+                for (Field field : fieldList) {
+                    // 此处没有做字段与列的自动转化
+                    String columnName = field.getName();
+                    setFieldValByName(columnName, "1234567890", metaObject);
+                }
+            }
+
+            @Override
+            public void updateFill(MetaObject metaObject) {
+
+            }
+        };
+    }
+    
+    @Bean
+    public AnnotationHandler annotationHandler() {
+        return new AnnotationHandler() {
+
+            /**
+             * 结合{@link com.baomidou.mybatisplus.test.h2.customfill.model.TestModel#getA()}简单实现{@link InsertUpdateFill} 的获取过程
+             *
+             * @param field           字段
+             * @param annotationClass 要获取的注解class
+             * @param <T>
+             * @return
+             */
+            @Override
+            public <T extends Annotation > T getAnnotation(Field field, Class<T> annotationClass) {
+
+                T annotation = field.getAnnotation(annotationClass);
+                if (annotationClass != TableField.class) {
+                    return annotation;
+                }
+
+                Annotation insertUpdateFillAnno = field.getAnnotation(InsertUpdateFill.class);
+                if (insertUpdateFillAnno == null) {
+                    return annotation;
+                }
+
+        /*
+         如果是要获取TableField场景,尝试判断是否存在InsertUpdateFill,存在则假定存在@TableField(fill = FieldFill.INSERT_UPDATE)的配置,
+         实际应用场景,应采取更加通用的方式,例如Spring的AnnotationUtils等
+         */
+                if (annotation != null) {
+                    TableField finalAnnotation = (TableField) annotation;
+                    annotation = (T) new TableField() {
+                        @Override
+                        public Class<? extends Annotation> annotationType() {
+                            return finalAnnotation.annotationType();
+                        }
+
+                        @Override
+                        public String value() {
+                            return finalAnnotation.value();
+                        }
+
+                        @Override
+                        public boolean exist() {
+                            return finalAnnotation.exist();
+                        }
+
+                        @Override
+                        public String condition() {
+                            return finalAnnotation.value();
+                        }
+
+                        @Override
+                        public String update() {
+                            return finalAnnotation.update();
+                        }
+
+                        @Override
+                        public FieldStrategy insertStrategy() {
+                            return finalAnnotation.insertStrategy();
+                        }
+
+                        @Override
+                        public FieldStrategy updateStrategy() {
+                            return finalAnnotation.updateStrategy();
+                        }
+
+                        @Override
+                        public FieldStrategy whereStrategy() {
+                            return finalAnnotation.whereStrategy();
+                        }
+
+                        @Override
+                        public FieldFill fill() {
+                            return FieldFill.INSERT_UPDATE;
+                        }
+
+                        @Override
+                        public boolean select() {
+                            return finalAnnotation.select();
+                        }
+
+                        @Override
+                        public boolean keepGlobalFormat() {
+                            return finalAnnotation.keepGlobalFormat();
+                        }
+
+                        @Override
+                        public String property() {
+                            return finalAnnotation.value();
+                        }
+
+                        @Override
+                        public JdbcType jdbcType() {
+                            return finalAnnotation.jdbcType();
+                        }
+
+                        @Override
+                        public Class<? extends TypeHandler> typeHandler() {
+                            return finalAnnotation.typeHandler();
+                        }
+
+                        @Override
+                        public boolean javaType() {
+                            return finalAnnotation.javaType();
+                        }
+
+                        @Override
+                        public String numericScale() {
+                            return finalAnnotation.value();
+                        }
+                    };
+                } else {
+                    annotation = (T) new TableField() {
+                        @Override
+                        public Class<? extends Annotation> annotationType() {
+                            return TableField.class;
+                        }
+
+                        @Override
+                        public String value() {
+                            return "";
+                        }
+
+                        @Override
+                        public boolean exist() {
+                            return true;
+                        }
+
+                        @Override
+                        public String condition() {
+                            return "";
+                        }
+
+                        @Override
+                        public String update() {
+                            return "";
+                        }
+
+                        @Override
+                        public FieldStrategy insertStrategy() {
+                            return FieldStrategy.DEFAULT;
+                        }
+
+                        @Override
+                        public FieldStrategy updateStrategy() {
+                            return FieldStrategy.DEFAULT;
+                        }
+
+                        @Override
+                        public FieldStrategy whereStrategy() {
+                            return FieldStrategy.DEFAULT;
+                        }
+
+                        @Override
+                        public FieldFill fill() {
+                            return FieldFill.INSERT_UPDATE;
+                        }
+
+                        @Override
+                        public boolean select() {
+                            return true;
+                        }
+
+                        @Override
+                        public boolean keepGlobalFormat() {
+                            return false;
+                        }
+
+                        @Override
+                        public String property() {
+                            return "";
+                        }
+
+                        @Override
+                        public JdbcType jdbcType() {
+                            return JdbcType.UNDEFINED;
+                        }
+
+                        @Override
+                        public Class<? extends TypeHandler> typeHandler() {
+                            return UnknownTypeHandler.class;
+                        }
+
+                        @Override
+                        public boolean javaType() {
+                            return false;
+                        }
+
+                        @Override
+                        public String numericScale() {
+                            return "";
+                        }
+                    };
+                }
+                return annotation;
+            }
+
+            @Override
+            public <T extends Annotation> boolean isAnnotationPresent(Field field, Class<T> annotationClass) {
+                return getAnnotation(field, annotationClass) != null;
+            }
+        };
+    }
+
+}

+ 17 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/customfill/annotation/InsertUpdateFill.java

@@ -0,0 +1,17 @@
+package com.baomidou.mybatisplus.test.h2.customfill.annotation;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.FIELD})
+@TableField(fill = FieldFill.INSERT_UPDATE)
+public @interface InsertUpdateFill {
+}

+ 8 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/customfill/mapper/TestModelMapper.java

@@ -0,0 +1,8 @@
+package com.baomidou.mybatisplus.test.h2.customfill.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.test.h2.customfill.model.TestModel;
+
+public interface TestModelMapper extends BaseMapper<TestModel> {
+
+}

+ 18 - 0
mybatis-plus/src/test/java/com/baomidou/mybatisplus/test/h2/customfill/model/TestModel.java

@@ -0,0 +1,18 @@
+package com.baomidou.mybatisplus.test.h2.customfill.model;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.test.h2.customfill.annotation.InsertUpdateFill;
+import lombok.Data;
+
+@Data
+@TableName(value = "t_fill_test")
+public class TestModel {
+
+    private Long id;
+    @InsertUpdateFill
+    private String a;
+    @TableField(fill = FieldFill.INSERT_UPDATE)
+    private String b;
+}

+ 6 - 0
mybatis-plus/src/test/resources/customfilltest/init.ddl.sql

@@ -0,0 +1,6 @@
+CREATE TABLE IF NOT EXISTS  t_fill_test (
+	id BIGINT(20) NOT NULL,
+	a VARCHAR(30) NULL DEFAULT NULL ,
+	b VARCHAR(30) NULL DEFAULT NULL ,
+	PRIMARY KEY (id)
+);

+ 14 - 0
mybatis-plus/src/test/resources/h2/spring-custom-fill-test-h2.xml

@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xmlns:context="http://www.springframework.org/schema/context"
+       xmlns="http://www.springframework.org/schema/beans"
+       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+           http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
+
+    <context:component-scan base-package="com.baomidou.mybatisplus.test.h2.customfill"/>
+
+    <bean class="com.baomidou.mybatisplus.test.h2.config.DBConfig">
+        <property name="locationPattern" value="classpath:/customfilltest/*.sql"/>
+    </bean>
+
+</beans>