如何覆盖 getOrderSubtotalAfterDiscounts 以从 Hybris 中的小计中排除受限产品

How to override getOrderSubtotalAfterDiscounts to exclude restricted product from subtotal in Hybris

可能是 experts.hybris

的重复问题

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

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

变得空

方面:

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>

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

你不需要在这里使用 AOP,只需覆盖 OrderPromotion 就可以了:

<bean id="de.hybris.platform.promotions.jalo.OrderPromotion" 
    class="foo.bar.CustomOrderPromotion" 
    scope="prototype">

    <property name="timeService" ref="timeService" />
    <property name="cartService" ref="cartService" />

</bean>

注意:您的 CustomOrderPromotion 应该继承自 OrderPromotion

您的方面没有导入 de.hybris.platform.promotions.jalo.OrderPromotion 并且不在同一个包中。所以我真的很想知道为什么它甚至应该编译成你正在尝试使用的OrderPromotion

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

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


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

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

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

  • 将两个方法执行拉出到两个单独的切入点,
  • 然后使用 args()target() 以便将捕获的值直接绑定到切入点参数
  • 然后在您的建议方法中组合切入点和所有参数:
@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],而是完美的类型安全参数绑定。

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

这是有效的,我已经通过复制你所有的十几个被归类为假人的方法测试了它的效果(这里的代码太多 post)。