【问题标题】:Asp.Net MVC Controller: declarative AOP with Spring.NetAsp.Net MVC 控制器:使用 Spring.Net 的声明式 AOP
【发布时间】:2010-12-04 04:26:11
【问题描述】:

Spring.Net Aspects 是否可能不适用于 Asp.Net 控制器?

我想在控制器的 Action 方法上配置事务,但代理似乎没有触发。

<object id="ControllerClassPointcut" type="Spring.Aop.Support.SdkRegularExpressionMethodPointcut, Spring.Aop">
  <property name="patterns">
    <list>
      <value>xxx.Controllers.CompanyController.*</value>
    </list>
  </property>
</object>

<aop:config>
  <aop:advisor pointcut-ref="ControllerClassPointcut" advice-ref="TxAdvice"/>
  <!-- TxAdvice taken from ServiceContext -->
</aop:config>

<tx:advice id="TxAdvice" transaction-manager="TransactionManager">
  <tx:attributes>
    <tx:method name="*" propagation="Required"/>
  </tx:attributes>
</tx:advice>

而CompanyController的action方法是:

    [HttpPost]
    public virtual ActionResult Create(Guid id, CompanyonViewModel vm)
    {
       ...
    }

但我的建议没有生效,虽然切入点被识别。如果我将控制器以外的其他类作为切入点,它就可以工作。

对于某些方法,建议有效。例如对于存储库的设置器。但是 Sprint.Net 不承认调用了动作方法“Create”

候选人是:'xxx.Controllers.CompanyController.set_CompanyService';模式是'xxx.Controllers.CompanyController.*';匹配=真 候选顾问 [DefaultObjectFactoryPointcutAdvisor: 切入点 [Spring.Aop.Support.SdkRegularExpressionMethodPointcut];建议对象 = 'TxAdvice'] 接受 targetType [xxx.Controllers.CompanyController]

感谢您的帮助

【问题讨论】:

标签: asp.net-mvc asp.net-mvc-2 aop spring.net


【解决方案1】:

你可以试试配置吗

<aop:config proxy-target-type="true">

这将创建一个基于继承的代理。您可能需要下载最近的 spirng.net 每晚版本才能使用(不是 1.3.0)。

【讨论】:

  • 马克,您能否对我今天早些时候的回答发表快速评论?如有任何反馈,我将不胜感激。
  • 我不喜欢夜间构建,所以我不会使用这个解决方案。但感谢您的回答
  • 根据docs,您也可以将其放入 tx 注释驱动设置中。
  • 仅设置proxy-target-type="true" 是不够的,因为这仍然委托给内部目标控制器。目标控制器自己调用 action 方法,而不是访问代理,因此不会发生拦截。一种可行的替代方法是使用InheritanceBasedConfigurer,例如,请参阅stackoverflow.com/questions/9114762/…
【解决方案2】:

[Transaction] 属性(使用 Spring.AOP 有效)也有类似的问题。 在我的例子中,我从同一个类中调用了[Transaction] 标记的方法,并且对事务通知没有触发感到惊讶。

解释是,当从类中调用 [Transaction] 标记的方法时,您持有对真实实例的引用而不是 AOP 代理的实例,因此调用不会被拦截。

当向 MVC 应用发出请求时,会从请求 url 中选择一个控制器(来自 IControllerFactory 实例)。在这个控制器上,Execute 方法被调用,该方法又负责调用动作。所以我认为动作方法总是从控制器内部调用。这意味着根据定义,动作方法永远不会被拦截。这可以解释为什么这些切入点会被识别,但不会触发。

如果我参加其他课程而不是 控制器作为切入点起作用

它还解释了为什么在控制器之外的其他类上的切入点会触发:它们很可能是从控制器调用的,控制器将持有对其他类实例的 AOP 代理引用。

...对于某些方法,建议有效...例如,对于 setter 存储库

我假设您的(例如)CompanyController.CustomerController 具有使用 DI 设置的属性 CustomerRepository。这个切入点触发是有道理的,因为 setter 是从 CompanyController.CustomerController 外部调用的,例如由您的 DI 容器(或您的 ControllerFactory)调用。

一种解决方案可能是引入服务对象,您可以在其上定义您现在在控制器上拥有的事务建议。从您的控制器中,您可以调用这些服务对象上的方法 - 然后切入点将被触发。

【讨论】:

  • 这个话题在Java Spring forum也有讨论
  • 但我不确定我是否会建议遵循用户“gspeed”最后发布的解决方案;最好听从迈克的建议
猜你喜欢
  • 2011-02-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-18
  • 1970-01-01
相关资源
最近更新 更多