瀏覽代碼

增加数据操作事件模型

woody 11 月之前
父節點
當前提交
34a3bb6d20

+ 1 - 1
framework-common/src/main/java/com/chelvc/framework/common/util/ObjectUtils.java

@@ -882,7 +882,7 @@ public final class ObjectUtils {
         if (type instanceof ParameterizedType) {
             return (Class<?>) ((ParameterizedType) type).getRawType();
         }
-        return (Class<?>) type;
+        return type instanceof Class ? (Class<?>) type : null;
     }
 
     /**

+ 102 - 0
framework-database/src/main/java/com/chelvc/framework/database/context/DatabaseContextHolder.java

@@ -68,8 +68,10 @@ import com.chelvc.framework.database.entity.Creatable;
 import com.chelvc.framework.database.entity.Deletable;
 import com.chelvc.framework.database.entity.Entity;
 import com.chelvc.framework.database.entity.Updatable;
+import com.chelvc.framework.database.support.EventService;
 import com.google.common.collect.Maps;
 import lombok.NonNull;
+import org.apache.commons.lang3.tuple.Pair;
 import org.mybatis.spring.SqlSessionTemplate;
 import org.springframework.context.ApplicationContext;
 import org.springframework.util.CollectionUtils;
@@ -824,4 +826,104 @@ public final class DatabaseContextHolder {
         }
         return Pagination.<T>builder().total(page.getTotal()).pages(page.getPages()).records(records).build();
     }
+
+    /**
+     * 发布数据新增事件
+     *
+     * @param type   对象类型
+     * @param entity 新增对象实例
+     * @param <T>    数据类型
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> void publishAddition(@NonNull Class<T> type, @NonNull T entity) {
+        IService<T> service = lookupEntityService(type);
+        if (service instanceof EventService) {
+            ((EventService<T>) service).publishAddition(entity);
+        }
+    }
+
+    /**
+     * 批量发布数据新增事件
+     *
+     * @param type     对象类型
+     * @param entities 新增对象实例集合
+     * @param <T>      数据类型
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> void publishAddition(@NonNull Class<T> type, @NonNull Collection<T> entities) {
+        if (ObjectUtils.isEmpty(entities)) {
+            return;
+        }
+        IService<T> service = lookupEntityService(type);
+        if (service instanceof EventService) {
+            ((EventService<T>) service).publishAddition(entities);
+        }
+    }
+
+    /**
+     * 发布数据删除事件
+     *
+     * @param type   对象类型
+     * @param entity 删除对象实例
+     * @param <T>    数据类型
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> void publishDeletion(@NonNull Class<T> type, @NonNull T entity) {
+        IService<T> service = lookupEntityService(type);
+        if (service instanceof EventService) {
+            ((EventService<T>) service).publishDeletion(entity);
+        }
+    }
+
+    /**
+     * 批量发布数据删除事件
+     *
+     * @param type     对象类型
+     * @param entities 删除对象实例集合
+     * @param <T>      数据类型
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> void publishDeletion(@NonNull Class<T> type, @NonNull Collection<T> entities) {
+        if (ObjectUtils.isEmpty(entities)) {
+            return;
+        }
+        IService<T> service = lookupEntityService(type);
+        if (service instanceof EventService) {
+            ((EventService<T>) service).publishDeletion(entities);
+        }
+    }
+
+    /**
+     * 发布数据更新事件
+     *
+     * @param type   对象类型
+     * @param before 更新前对象实例
+     * @param after  更新后对象实例
+     * @param <T>    数据类型
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> void publishModification(@NonNull Class<T> type, @NonNull T before, @NonNull T after) {
+        IService<T> service = lookupEntityService(type);
+        if (service instanceof EventService) {
+            ((EventService<T>) service).publishModification(before, after);
+        }
+    }
+
+    /**
+     * 批量发布数据更新事件
+     *
+     * @param type  对象类型
+     * @param pairs 更新前后对象实例集合
+     * @param <T>   数据类型
+     */
+    @SuppressWarnings("unchecked")
+    public static <T> void publishModification(@NonNull Class<T> type, @NonNull Collection<Pair<T, T>> pairs) {
+        if (ObjectUtils.isEmpty(pairs)) {
+            return;
+        }
+        IService<T> service = lookupEntityService(type);
+        if (service instanceof EventService) {
+            ((EventService<T>) service).publishModification(pairs);
+        }
+    }
 }

+ 33 - 0
framework-database/src/main/java/com/chelvc/framework/database/listener/AddListener.java

@@ -0,0 +1,33 @@
+package com.chelvc.framework.database.listener;
+
+import java.util.Collection;
+
+import com.chelvc.framework.common.util.ObjectUtils;
+
+/**
+ * 数据新增操作监听器接口
+ *
+ * @param <T> 数据类型
+ * @author Woody
+ * @date 2024/4/30
+ */
+public interface AddListener<T> extends OperateListener<T> {
+    /**
+     * 监听数据新增
+     *
+     * @param entity 对象实例
+     */
+    default void add(T entity) {
+    }
+
+    /**
+     * 监听数据批量新增
+     *
+     * @param entities 对象实例集合
+     */
+    default void add(Collection<T> entities) {
+        if (ObjectUtils.notEmpty(entities)) {
+            entities.forEach(this::add);
+        }
+    }
+}

+ 34 - 0
framework-database/src/main/java/com/chelvc/framework/database/listener/DeleteListener.java

@@ -0,0 +1,34 @@
+package com.chelvc.framework.database.listener;
+
+import java.util.Collection;
+
+import com.chelvc.framework.common.util.ObjectUtils;
+
+
+/**
+ * 数据删除操作监听器接口
+ *
+ * @param <T> 数据类型
+ * @author Woody
+ * @date 2024/4/30
+ */
+public interface DeleteListener<T> extends OperateListener<T> {
+    /**
+     * 监听数据删除
+     *
+     * @param entity 对象实例
+     */
+    default void delete(T entity) {
+    }
+
+    /**
+     * 监听数据批量删除
+     *
+     * @param entities 对象实例集合
+     */
+    default void delete(Collection<T> entities) {
+        if (ObjectUtils.notEmpty(entities)) {
+            entities.forEach(this::delete);
+        }
+    }
+}

+ 35 - 0
framework-database/src/main/java/com/chelvc/framework/database/listener/ModifyListener.java

@@ -0,0 +1,35 @@
+package com.chelvc.framework.database.listener;
+
+import java.util.Collection;
+
+import com.chelvc.framework.common.util.ObjectUtils;
+import org.apache.commons.lang3.tuple.Pair;
+
+/**
+ * 数据更新操作监听器接口
+ *
+ * @param <T> 数据类型
+ * @author Woody
+ * @date 2024/4/30
+ */
+public interface ModifyListener<T> extends OperateListener<T> {
+    /**
+     * 监听数据更新
+     *
+     * @param before 更新前对象实例
+     * @param after  更新后对象实例
+     */
+    default void modify(T before, T after) {
+    }
+
+    /**
+     * 监听数据批量更新
+     *
+     * @param pairs 更新前后对象实例集合
+     */
+    default void modify(Collection<Pair<T, T>> pairs) {
+        if (ObjectUtils.notEmpty(pairs)) {
+            pairs.forEach(pair -> this.modify(pair.getLeft(), pair.getRight()));
+        }
+    }
+}

+ 11 - 0
framework-database/src/main/java/com/chelvc/framework/database/listener/OperateListener.java

@@ -0,0 +1,11 @@
+package com.chelvc.framework.database.listener;
+
+/**
+ * 数据操作事件监听器接口
+ *
+ * @param <T> 数据类型
+ * @author Woody
+ * @date 2024/4/29
+ */
+public interface OperateListener<T> {
+}

+ 91 - 6
framework-database/src/main/java/com/chelvc/framework/database/support/DefaultEnhanceService.java

@@ -1,9 +1,24 @@
 package com.chelvc.framework.database.support;
 
+import java.lang.reflect.Type;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
-import com.baomidou.mybatisplus.extension.conditions.query.QueryChainWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.chelvc.framework.common.util.ObjectUtils;
+import com.chelvc.framework.database.listener.AddListener;
+import com.chelvc.framework.database.listener.DeleteListener;
+import com.chelvc.framework.database.listener.ModifyListener;
+import com.chelvc.framework.database.listener.OperateListener;
+import com.google.common.collect.Lists;
+import lombok.NonNull;
+import org.apache.commons.lang3.tuple.Pair;
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
 
 /**
  * 业务增强操作默认实现
@@ -13,12 +28,15 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  * @author Woody
  * @date 2024/4/29
  */
-public class DefaultEnhanceService<M extends BaseMapper<T>, T> extends ServiceImpl<M, T> implements EnhanceService<T> {
+public class DefaultEnhanceService<M extends BaseMapper<T>, T> extends ServiceImpl<M, T>
+        implements EnhanceService<T>, ApplicationContextAware {
+    private final List<AddListener<T>> addListeners = Lists.newArrayListWithCapacity(0);
+    private final List<DeleteListener<T>> deleteListeners = Lists.newArrayListWithCapacity(0);
+    private final List<ModifyListener<T>> modifyListeners = Lists.newArrayListWithCapacity(0);
+
     @Override
-    public QueryChainWrapper<T> query() {
-        QueryChainWrapper<T> query = super.query();
-        query.setEntityClass(this.getEntityClass());
-        return query;
+    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
+        applicationContext.getBeansOfType(OperateListener.class).values().forEach(this::register);
     }
 
     @Override
@@ -27,4 +45,71 @@ public class DefaultEnhanceService<M extends BaseMapper<T>, T> extends ServiceIm
         query.setEntityClass(this.getEntityClass());
         return query;
     }
+
+    @Override
+    public synchronized void register(@NonNull OperateListener<T> listener) {
+        // 校验监听数据类型与当前数据模型类型是否匹配
+        Class<?> type;
+        if (listener instanceof AddListener) {
+            type = AddListener.class;
+        } else if (listener instanceof DeleteListener) {
+            type = DeleteListener.class;
+        } else if (listener instanceof ModifyListener) {
+            type = ModifyListener.class;
+        } else {
+            type = OperateListener.class;
+        }
+        Type parameterized = ObjectUtils.lookupSuperclassParameterized(listener.getClass(), type);
+        if (ObjectUtils.type2class(parameterized) != this.getEntityClass()) {
+            return;
+        }
+
+        // 注册监听器
+        if (listener instanceof AddListener) {
+            this.addListeners.add((AddListener<T>) listener);
+        } else if (listener instanceof DeleteListener) {
+            this.deleteListeners.add((DeleteListener<T>) listener);
+        } else if (listener instanceof ModifyListener) {
+            this.modifyListeners.add((ModifyListener<T>) listener);
+        }
+    }
+
+    @Override
+    public void publishAddition(@NonNull T entity) {
+        this.addListeners.forEach(listener -> listener.add(entity));
+    }
+
+    @Override
+    public void publishAddition(@NonNull Collection<T> entities) {
+        if (ObjectUtils.notEmpty(entities)) {
+            Collection<T> unmodifiable = Collections.unmodifiableCollection(entities);
+            this.addListeners.forEach(listener -> listener.add(unmodifiable));
+        }
+    }
+
+    @Override
+    public void publishDeletion(@NonNull T entity) {
+        this.deleteListeners.forEach(listener -> listener.delete(entity));
+    }
+
+    @Override
+    public void publishDeletion(@NonNull Collection<T> entities) {
+        if (ObjectUtils.notEmpty(entities)) {
+            Collection<T> unmodifiable = Collections.unmodifiableCollection(entities);
+            this.deleteListeners.forEach(listener -> listener.delete(unmodifiable));
+        }
+    }
+
+    @Override
+    public void publishModification(@NonNull T before, @NonNull T after) {
+        this.modifyListeners.forEach(listener -> listener.modify(before, after));
+    }
+
+    @Override
+    public void publishModification(@NonNull Collection<Pair<T, T>> pairs) {
+        if (ObjectUtils.notEmpty(pairs)) {
+            Collection<Pair<T, T>> unmodifiable = Collections.unmodifiableCollection(pairs);
+            this.modifyListeners.forEach(listener -> listener.modify(unmodifiable));
+        }
+    }
 }

+ 1 - 1
framework-database/src/main/java/com/chelvc/framework/database/support/EnhanceService.java

@@ -23,7 +23,7 @@ import lombok.NonNull;
  * @author Woody
  * @date 2024/3/10
  */
-public interface EnhanceService<T> extends IService<T> {
+public interface EnhanceService<T> extends IService<T>, EventService<T> {
     /**
      * 根据ID修改实体
      *

+ 71 - 0
framework-database/src/main/java/com/chelvc/framework/database/support/EventService.java

@@ -0,0 +1,71 @@
+package com.chelvc.framework.database.support;
+
+import java.util.Collection;
+
+import com.chelvc.framework.database.listener.OperateListener;
+import org.apache.commons.lang3.tuple.Pair;
+
+/**
+ * 数据操作事件业务接口
+ *
+ * @author Woody
+ * @date 2024/4/30
+ */
+public interface EventService<T> {
+    /**
+     * 注册操作事件监听器
+     *
+     * @param listener 监听器实例
+     */
+    default void register(OperateListener<T> listener) {
+    }
+
+    /**
+     * 发布数据新增事件
+     *
+     * @param entity 新增对象实例
+     */
+    default void publishAddition(T entity) {
+    }
+
+    /**
+     * 批量发布数据新增事件
+     *
+     * @param entities 新增对象实例集合
+     */
+    default void publishAddition(Collection<T> entities) {
+    }
+
+    /**
+     * 发布数据删除事件
+     *
+     * @param entity 删除对象实例
+     */
+    default void publishDeletion(T entity) {
+    }
+
+    /**
+     * 批量发布数据删除事件
+     *
+     * @param entities 删除对象实例集合
+     */
+    default void publishDeletion(Collection<T> entities) {
+    }
+
+    /**
+     * 发布数据更新事件
+     *
+     * @param before 更新前对象实例
+     * @param after  更新后对象实例
+     */
+    default void publishModification(T before, T after) {
+    }
+
+    /**
+     * 批量发布数据更新事件
+     *
+     * @param pairs 更新前后对象实例集合
+     */
+    default void publishModification(Collection<Pair<T, T>> pairs) {
+    }
+}