Java 拦截器和装饰器之间的区别

Java 拦截器和装饰器之间的区别,java,jakarta-ee,design-patterns,decorator,interceptor,Java,Jakarta Ee,Design Patterns,Decorator,Interceptor,Java中的拦截器和装饰器之间有什么区别吗?严格地说,我可以用decorator实现拦截器不可能实现的东西吗 除了我必须检查方法名称以在拦截器中添加方法特定行为的问题: @Nice @Interceptor public class NiceGreeterInterceptor { @AroundInvoke public Object decorate(InvocationContext ic) throws Exception { Method method = ic.get

Java中的拦截器和装饰器之间有什么区别吗?严格地说,我可以用decorator实现拦截器不可能实现的东西吗

除了我必须检查方法名称以在拦截器中添加方法特定行为的问题:

@Nice
@Interceptor
public class NiceGreeterInterceptor {
  @AroundInvoke
  public Object decorate(InvocationContext ic) throws Exception {
    Method method = ic.getMethod();
    String methodName = method.getName();
    Object result = ic.proceed();
    if (methodName.equals("greet")) {
      return "NEW " + result;
    }
  }
}
拦截器:

@Nice
@Interceptor
public class NiceGreeterInterceptor {
  @AroundInvoke
  public Object decorate(InvocationContext ic) throws Exception {
    Method method = ic.getMethod();
    String methodName = method.getName();
    Object result = ic.proceed();
    if (methodName.equals("greet")) {
      return "NEW " + result;
    }
  }
}
装饰师:

@Decorator
public class GreeterDecorator implements Greeter {
  @Inject
  @Any
  @Delegate
  private Greeter greeter;

  @Override
  public String greet() {
    return "NEW " + greeter.greet();
  }
}
或者说我可以用拦截器复制装饰器的所有行为,但使用装饰器更舒适,这是合理的吗?

Decorator 一个不同点是,正如您的示例所示,对于decorator,您通常会为每个装饰类/接口编写一个decorator

装饰器示例 拦截器 使用拦截器,这是概念的一部分,您可以为一组类/方法编写一个拦截器,例如,您可以拦截所有方法,并确保事务在调用之前打开,在调用之后关闭

拦截器示例 声明一个(要匹配的内容),在这里您可以匹配MyDao类中以insert开头、具有任何参数和任何返回类型的任何方法

@Pointcut("execution(* com.example.dao.MyDao.insert*(..))")
public void insertPointcut() {
}
然后声明一个引用切入点的

@Around(value = "com.example.SystemArchitecture.insertPointcut()")
public void interceptMethod(ProceedingJoinPoint pjp) {
        // do pre-work
        Object retVal = pjp.proceed();
        // do post work
        return retVal;
    }
}

拦截器更灵活,但假设您更改了方法名称,如果您使用decorator,您可能会遇到编译器错误,使用拦截器,它将不匹配并且不会执行您的“环绕”逻辑。

Decorators与拦截器非常相似,但有两个有趣的区别:

  • 装饰器必须实现它所装饰的接口(但可以是抽象的,因此它不必实现方法)

  • 装饰器可以具有对其装饰的对象的引用。这是通过注射来完成的


  • Ref:

    通常,装饰器用于添加新功能或修改现有功能。它使用组合作为继承的替代。装饰器通常提供装饰类中不可用的附加API(方法)

    另一方面,AOP(例如拦截器)用于增强现有行为。它不会添加额外的API,通常也不会修改现有的功能。它是通过调用现有功能触发的,并通过采取一些操作进行响应;但是现有的功能以及现有的API保持不变

    我不熟悉JEE实现,因此它们可能模糊了这两种模式之间的界限。比较的要点是

    • @Interceptor
      能否引入新方法或仅在现有方法周围执行
    • @Interceptor
      是否可以覆盖现有方法或仅附加其他行为
    • @Decorator
      可以跨包和类层次结构应用,还是受其中一个层次结构的约束

    除了这两种模式之间的功能差异之外,考虑潜在的性能差异也可能是有趣的。我预计

    @Interceptor
    会慢得多,因为它需要在运行时检查方法调用,而
    @Decorator
    调用可以在编译时解析。

    但是拦截器也可以使用
    ic.getTarget()获取引用
    decorator自动应用于实现相同接口的类(使用自定义限定符除外)。所以不止一个装饰类。同意,它是一对一或一对多,但同样,你有接口,所以它是高度面向对象的。使用AOP,它更灵活,因为您可以使用类型筛选器(例如,代理某个类的所有方法)以及裸字符串reg ex匹配筛选器(例如,代理所有以select开头的方法,并且是com.example.dao包的一部分)。您能否用regex匹配筛选器的示例将您的注释添加到您的答案中,没有完全的reg ex支持,但您有一些通配符匹配。谢谢。所以理论上我可以用拦截器复制装饰器的所有行为?