You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建拦截器监听列表修改,自动同步更新QaService产品类型?

通用实现方案

提供两种落地方式,可根据你的项目场景选择:


方案1:封装可监听的可变列表(侵入性最低,无遗漏)

核心思路是代理MutableList的所有修改方法,操作执行完成后自动触发校验逻辑,从根源上避免新增修改方法时遗漏校验。

步骤1:通用化拦截器实现

import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Component

// 泛型化拦截器,支持任意元素类型的列表
@Component
class ListProductInterceptor {
    @Autowired
    private lateinit var qaService: QaService

    fun <T> intercept(productType: ProductTypeEnum, list: List<T>) {
        if (list.isEmpty()) {
            qaService.removeProductType(productType)
        } else if (!qaService.typeList.contains(productType)) {
            qaService.addProductType(productType)
        }
    }
}

步骤2:封装可自动触发拦截的列表实现

class ObservableMutableList<T>(
    private val productType: ProductTypeEnum,
    private val delegate: MutableList<T> = mutableListOf(),
    // 从Spring上下文获取拦截器实例,或者构造时传入
    private val interceptor: ListProductInterceptor = SpringContextUtil.getBean(ListProductInterceptor::class.java)
) : MutableList<T> by delegate {

    private fun afterModify() {
        interceptor.intercept(productType, this)
    }

    override fun add(element: T): Boolean {
        return delegate.add(element).also { afterModify() }
    }

    override fun add(index: Int, element: T) {
        delegate.add(index, element).also { afterModify() }
    }

    override fun addAll(elements: Collection<T>): Boolean {
        return delegate.addAll(elements).also { afterModify() }
    }

    override fun addAll(index: Int, elements: Collection<T>): Boolean {
        return delegate.addAll(index, elements).also { afterModify() }
    }

    override fun remove(element: T): Boolean {
        return delegate.remove(element).also { afterModify() }
    }

    override fun removeAt(index: Int): T {
        return delegate.removeAt(index).also { afterModify() }
    }

    override fun removeAll(elements: Collection<T>): Boolean {
        return delegate.removeAll(elements).also { afterModify() }
    }

    override fun retainAll(elements: Collection<T>): Boolean {
        return delegate.retainAll(elements).also { afterModify() }
    }

    override fun clear() {
        delegate.clear().also { afterModify() }
    }
}

步骤3:业务层使用

直接替换原有MutableList定义即可,所有列表操作都会自动触发校验,无需在每个业务方法中写重复逻辑:

class WarehouseService: IWarehouseService {
    // 直接定义为监听列表,指定对应的产品类型即可
    val tiles = ObservableMutableList<Tile>(ProductTypeEnum.Tile)
    // 其他类型的列表同理
    val woods = ObservableMutableList<Wood>(ProductTypeEnum.Wood)
  
    override fun destroyProduct() {
        // 仅处理业务逻辑,无需手动加校验
        tiles.removeLast()
    }
}

方案2:Spring AOP切面实现(适合存量业务改造)

如果不想修改现有列表的定义,可通过切面加注解的方式实现,仅需要给修改列表的方法加注解即可。

步骤1:定义标记注解

@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME)
annotation class SyncProductType(
    val productType: ProductTypeEnum,
    val listFieldName: String // 指定要校验的列表字段名
)

步骤2:实现切面逻辑

@Aspect
@Component
class ProductTypeSyncAspect {
    @Autowired
    private lateinit var qaService: QaService

    @After("@annotation(syncProductType)")
    fun afterModifyList(joinPoint: JoinPoint, syncProductType: SyncProductType) {
        val target = joinPoint.target
        // 反射获取对应的列表字段
        val listField = target::class.java.getDeclaredField(syncProductType.listFieldName)
        listField.isAccessible = true
        val list = listField.get(target) as List<*>
        // 执行校验逻辑
        val productType = syncProductType.productType
        if (list.isEmpty()) {
            qaService.removeProductType(productType)
        } else if (!qaService.typeList.contains(productType)) {
            qaService.addProductType(productType)
        }
    }
}

步骤3:业务层使用

在所有修改对应列表的方法上加注解即可,新增方法只要加注解就不会遗漏校验:

class WarehouseService: IWarehouseService {
    val tiles = mutableListOf<Tile>()
    val woods = mutableListOf<Wood>()
  
    @SyncProductType(productType = ProductTypeEnum.Tile, listFieldName = "tiles")
    override fun destroyProduct() {
        // 仅处理业务逻辑
        tiles.removeLast()
    }

    @SyncProductType(productType = ProductTypeEnum.Wood, listFieldName = "woods")
    override fun addWood() {
        woods.add(Wood())
    }
}

方案选型建议

  • 优先选方案1:无额外注解成本,所有列表操作(包括直接调用列表的add/remove等方法)都会触发校验,不会出现遗漏
  • 若为存量项目,大量业务逻辑已经写完不想改动列表定义,可选方案2

内容的提问来源于stack exchange,提问作者Patrick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 06:36:00