java - 如何重写 getOrderSubtotalAfterDiscounts 以从 Hybris 的小计中排除受限产品

标签 java aspectj spring-aop sap-commerce-cloud promotions

可能是 experts.hybris 的重复问题

我们正在使用促销模块(已弃用)。 OOTB 如果您有产品限制并且您有混合购物车(具有允许和限制的产品),则促销(例如:订单阈值促销)将适用(计算)整个购物车总数。 理想情况下,受限制的产品价格应从购物车总额中排除以触发促销,这就是我想要实现的目标。

为此,我尝试使用 Spring AOP 覆盖 getOrderSubtotalAfterDiscounts 并且它也被调用。但在那里,我需要获取当前促销类实例 (OrderPromotion) 来调用 PromotionsManagerevaluateRestrictions。但使用 (OrderPromotion) pjp.getTarget() 总是得到 null

方面:

package com.myproject.aop;

@Aspect
public class AbstractOrderAOP
{

    private static final Logger LOG = Logger.getLogger(AbstractOrderAOP.class);


    @Pointcut("execution(public * *..OrderThresholdDiscountPercentagePromotion.evaluate(..)) && target(orderPromotion)")
    public void evaluatePointcut(OrderPromotion orderPromotion)
    {
        //
    }

    @Pointcut("execution(protected * de.hybris.platform.promotions.jalo.OrderPromotion.getOrderSubtotalAfterDiscounts(..)) && args(ctx, order)")
    public void subtotalPointcut(SessionContext ctx, AbstractOrder order)
    {
        //
    }

    @SuppressWarnings("boxing")
    @Around("evaluatePointcut(orderPromotion) && cflow(subtotalPointcut(ctx, order))")
    public Object getOrderSubtotalAfterDiscounts(ProceedingJoinPoint pjp, OrderPromotion orderPromotion, SessionContext ctx,
            AbstractOrder order)
    {
        LOG.info("here you go ....");
        return 0l;
    }
}

aop.xml

<aspectj>
    <weaver options="-Xset:weaveJavaxPackages=true">
        <include within="de.hybris.platform.promotions.jalo.OrderPromotion"/>
        <include within="de.hybris.platform.b2bacceleratorservices.jalo.promotions.OrderThresholdDiscountPercentagePromotion"/>
        <include within="com.myproject.extended.interceptor.*"/>
    </weaver>
    <aspects>
        <aspect name="com.myproject.aop.AbstractOrderAOP"/>
    </aspects>
</aspectj>

如有任何帮助或建议,我们将不胜感激!!

最佳答案

您的方面不导入 de.hybris.platform.promotions.jalo.OrderPromotion并且不在同一个包中。所以我真的想知道为什么它甚至应该通过强制转换来编译 OrderPromotion您正在尝试使用。

如果您的方面确实有导入,并且在将其复制到您的SO问题之前只是将其删除,我认为没有理由 pjp.getTarget()应该产生 null ,但有一个异常(exception):如果方法是静态的,那么它当然不会有要调用的目标对象,因为没有对象实例。在这种情况下,您的方面无法工作,您需要拦截另一个切入点。

由于 Hybris 似乎在网络上没有任何公共(public) JavaDoc,而且我从未使用过它,因此无法访问它,所以我不能肯定地说,我必须推测。


更新:好的,我旅行回来了,有一点时间来回答。基本上这个想法是得到

  • 调用实例方法的目标和
  • 来自静态方法的参数。

为了实现这一点,您可以使用 cflow()切入点,您可以通过它表示如果静态方法位于控制流中(即直接或间接调用)获取目标对象的实例方法,则应该捕获该静态方法的执行。你应该

  • 将两个方法执行拉出到两个单独的切入点中,
  • 然后使用 args()target()为了将捕获的值直接绑定(bind)到切入点参数
  • 然后将切入点和所有参数组合到您的建议方法中:
@Aspect
public class AbstractOrderAOP {

  // (...)

  @Pointcut(
    "execution(public * *..OrderThresholdDiscountPercentagePromotion.evaluate(..)) && " +
    "target(orderPromotion)"
  )
  public void evaluatePointcut(OrderPromotion orderPromotion) {}

  @Pointcut(
    "execution(protected * *..OrderPromotion.getOrderSubtotalAfterDiscounts(..)) && " +
    "args(ctx, order)"
  )
  public void subtotalPointcut(SessionContext ctx, AbstractOrder order) {}

  @Around("cflow(evaluatePointcut(orderPromotion)) && subtotalPointcut(ctx, order)")
  public Object getOrderSubtotalAfterDiscounts(
    ProceedingJoinPoint pjp,
    OrderPromotion orderPromotion,
    SessionContext ctx,
    AbstractOrder order
  ) {

    LOG.info("############ AbstractOrderAOP is being evaluated ############");
    try {
      final Object output = pjp.proceed();
    } catch (Throwable e) {
      e.printStackTrace();
    }

    ArrayList products = new ArrayList();

    // (...)

    return 0l;
  }

  // (...)
}

看到了吗?不再丑getTarget()getArgs()[0] ,但完全类型安全的参数绑定(bind)。

顺便说一句,您不需要将包名称缩写为 *..就像我一样。我只是想让它对您和这里的其他人来说更具可读性。

这是有效的,我已经通过复制所有被归类为傻瓜的十几个左右来测试它的效果(这里发布的代码太多)。

关于java - 如何重写 getOrderSubtotalAfterDiscounts 以从 Hybris 的小计中排除受限产品,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49726241/

相关文章:

java - Hibernate 执行简单查询花费的时间太长

java - 在java中创建lua接口(interface)

java - 组合多个切入点 AspectJ 返回adviceDidNotMatch 警告

注释参数的 Spring AOP 切入点

java - 为什么 @AfterReturning 从未被调用

java - 当在类和方法中添加带注释的事务时,如何使事务仅在方法中起作用?

java - 使用Spring Cache缓存一个大的值并用它输出一个较小的值?

java - 我可以将 Class.newInstance() 与构造函数参数一起使用吗?

spring - 建议 javax.persistence.EntityManager 与 AspectJ 不起作用

java - Spring AOP切面不拦截带注释的方法