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

时间:2016-02-29 18:04:56

标签: java java-ee design-patterns decorator interceptor

Java中的拦截器和装饰器之间是否存在任何差异?严格地说,我可以用装饰器实现一些拦截器无法实现的东西,反之亦然吗?

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

拦截器:

@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();
  }
}

或者说我可以用拦截器重现装饰器的所有行为,但是使用装饰器会更舒服吗?

3 个答案:

答案 0 :(得分:9)

一个区别是,正如您的示例所示,使用装饰器,您通常每1个装饰类/接口编写1个装饰器。

使用拦截器,它是AOP概念的一部分,你可以为一堆类/方法编写1个拦截器,例如:拦截所有DAO方法并确保事务在调用之前打开并在之后关闭。

春天AOP中拦截器的一个例子,首先你声明一个pointcut(匹配什么),在这里你匹配MyDao类中以 insert 开头的任何方法,有任何方法参数和任何返回类型。

@Pointcut("execution(* com.example.dao.MyDao.insert*(..))")
public void insertPointcut() {
}

然后你声明一个引用切入点的around advice

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

尽管如此,每个部分都有自己的优点/缺点。例如。拦截器更灵活,但想象你改变方法名称,如果你使用装饰器,你可能会得到一个编译器错误,有拦截器,它只是不匹配而不执行你的'around'逻辑。

答案 1 :(得分:3)

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

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

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

  • @Interceptor可以引入新方法还是仅围绕现有方法执行?
  • @Interceptor可以覆盖现有方法还是只附加其他行为?
  • @Decorator可以跨包使用吗?类层次结构,还是受其中一个约束?

除了两种模式之间的功能差异外,考虑潜在的性能差异也可能很有意思。我希望@Interceptor要慢得多,因为它需要在运行时检查方法调用,而@Decorator调用可以在编译时解析。

答案 2 :(得分:0)

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

  1. 装饰者必须实现它正在装饰的界面(但可以是抽象的,所以它不必实现这些方法)

  2. 装饰者可以引用它装饰的对象。它通过注射完成

  3. 参考:https://blog.frankel.ch/cdi-an-overview-part-2

相关问题