跳至主要內容

面向切面-拦截器

Mr.Hope大约 3 分钟

面向切面-拦截器

拦截器

拦截器(Interceptor)是一种非侵入式的机制,用于在函数执行前和执行后对函数进行逻辑扩展。以下是拦截器的基本特点和使用方法:

  1. 标识拦截器:使用方法上的 @Hook 注解可以标识方法为拦截器。拦截器分为前置拦截器和后置拦截器,前者需要实现 HookBefore 接口,后者需要实现 HookAfter 接口。
  2. 拦截器入参:拦截器的入参包含当前拦截函数的定义以及拦截函数的入参。拦截器可以根据函数定义与入参来处理执行逻辑。
  3. 拦截器配置:拦截器可以根据函数定义、函数类型、优先级等条件进行配置。可以使用 @Hook 注解或 Hook 模型的字段(如 modulemodelfun、函数类型、active)来筛选出对当前拦截方法生效的拦截器。
  4. 拦截器优先级:拦截器的优先级通过 priority 属性进行设置。优先级数字越小,拦截器越先执行。

拦截器提供了一种灵活的方式来扩展函数的功能,同时通过优,可以对拦截器的执行顺序和生效范围进行精细化的管理和调整。

属性解释

@Hook(module = {DemoModule.MODULE_MODULE},model = {PetShop.MODEL_MODEL},fun = {"sayHello"}, priority = Integer.MAX_VALUE, displayName = "sayHello扩展点")

这个注解的定义允许在类和方法级别使用,即 ElementType.TYPEElementType.METHOD。 这段代码定义了一个名为 Hook 的注解,它具有以下属性:

  • displayName: 用于指定拦截器的显示名称。
  • hookType: 拦截器类型,默认为 HookTypeEnum.BEFORE,表示前置拦截器。
  • functionTypes: 函数类型数组,用于指定拦截器适用的函数类型。
  • priority: 执行优先级,默认值为 MetaValueConstants.priorityForHook,数字越小表示优先级越高。
  • module: 执行模块数组,用于指定拦截器适用的执行模块。
  • model: 模型数组,用于指定拦截器适用的模型。
  • fun: 函数数组,用于指定拦截器适用的函数。
  • description: 拦截器的描述信息。
  • active: 是否激活拦截器,默认为 true

前置拦截器举例

package pro.shushi.pamirs.demo.core.hook;
...//import

@Component
public class PetShopSayHelloHookBefore implements HookBefore {
    @Override
    @Hook(module = {DemoModule.MODULE_MODULE},model = {PetShop.MODEL_MODEL},fun = {"sayHello"})
    public Object run(Function function, Object... args) {
        if(args!=null && args[0]!=null){
            PetShop arg = (PetShop)args[0];
            arg.setShopName("hookbefore:"+ arg.getShopName());
        }
        return args;
    }

}

后置拦截器举例

package pro.shushi.pamirs.demo.core.hook;
...//import
import pro.shushi.pamirs.meta.api.dto.fun.Function;

@Component
public class PetShopSayHelloHookAfter implements HookAfter {

    @Override
    @Hook(model = {PetShop.MODEL_MODEL},fun = {"sayHello"})
    public Object run(Function function, Object ret) {
        if (ret == null) {
            return null;
        }
        PetShop result =null;
        if (ret instanceof Object[]) {
            Object[] rets = (Object[])((Object[])ret);
            if (rets.length == 1) {
                result = (PetShop)rets[0];
            }
        } else {
            result = (PetShop)ret;
        }
        result.setShopName(result.getShopName()+":hookAfter");
        return result;
    }
}

注意点

  1. 不管前置拦截器,还是后置拦截器都可以配置多,根据拦截器的优先级priority属性可以对拦截器的执行顺序进行调整。priority数字越小,越先执行;
  2. 拦截器必须是jar依赖,不然执行会报错。配置拦截器注意配置过滤条件;
  3. 模块启动yml文件可以过滤不需要执行的hook,具体配置见模块之yml文件结构详解open in new window
  4. 不是由前端发起而是后端编程调用,默认不会生效,如果要生效请参考框架之元位指令open in new window