Spring AOP:在正在运行的应用程序中添加建议

时间:2011-06-04 07:12:07

标签: spring spring-aop

如何在不重新启动服务器的情况下在正在运行的应用程序中添加或删除Spring AOP个代理?

像这样的东西

    GenericApplicationContext ctx = new GenericApplicationContext();
    BeanDefinitionBuilder promotion4Advice = BeanDefinitionBuilder.rootBeanDefinition(Promotion4Action.class).addPropertyValue("discountPercentage", 0.5);
    promotion4Advice.addPropertyValue("discountCode", 16);
    promotion4Advice.addPropertyValue("discountComment", "50% on regular item");
    ctx.registerBeanDefinition("promotion4Advice", promotion4Advice.getBeanDefinition());

    BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(ProxyFactoryBean.class);
    builder.addPropertyValue("proxyTargetClass", true);
    builder.addPropertyValue("interceptorNames", new String[] {"promotion4Advice"});
    ctx.registerBeanDefinition("proxyFactoryBean", builder.getBeanDefinition());

我的XML配置如下所示:

<bean id="promotion4Advice"
    class="com.promotion.actions.Promotion4Action">
    <property name="discountPercentage" value="0.5" />
    <property name="discountCode" value="16" />
    <property name="discountComment" value="50% on regular item" />
</bean>
<aop:config proxy-target-class="true">
    <aop:aspect id="promotion4Aspect" ref="promotion4Advice">
        <aop:pointcut id="promotion4PointCut"
            expression="execution(* com.controller.ShoppingBagController.defaultHandler(javax.servlet.http.HttpServletRequest)) and args(request)" />

        <aop:before pointcut-ref="promotion4PointCut" method="applyPromotion4"
            arg-names="request" />
    </aop:aspect>
    <aop:aspect id="promotion4Aspect1" ref="promotion4Advice">
        <aop:pointcut id="promotion4PointCut1"
            expression="execution(* com.controller.ReviewOrderController.handleRequest(javax.servlet.http.HttpServletRequest)) and args(request)" />

        <aop:before pointcut-ref="promotion4PointCut1" method="interceptOrderDetails"
            arg-names="request" />
    </aop:aspect>
    <aop:aspect id="promotion4Aspect4" ref="promotion4Advice">
        <aop:pointcut id="promotion4PointCut4"
            expression="execution(* com.controller.ShoppingBagController.applyPromoCode(javax.servlet.http.HttpServletRequest, String, String)) and args(request, promoCode, mappedURL)" />

        <aop:after pointcut-ref="promotion4PointCut4" method="interceptPromoCode"
            arg-names="request,promoCode,mappedURL" />
    </aop:aspect>
</aop:config>

这是其中一个促销活动......就像上面我有其他3个并且希望能够通过aop动态配置它们而无需更改xml并重新启动服务器。请帮忙

1 个答案:

答案 0 :(得分:2)

我认为你不能,主要是因为Spring在上下文启动时连线bean。这意味着如果bean A被注入bean B而前者不是任何代理的包装器,它将被直接注入。

当然,您可以使用A,将其包装在代理中并将其放回容器中(作为副本A')。但B根本不了解A'

如果您事先知道哪些bean受动态添加/删除方面的影响,请在启动时不做任何事情(例如调用NoOpStrategy类)进行热切包装。当您需要“添加”方面时,只需将该策略更改为其他内容。