使用Spring.Net的不引人注目的AOP

Dav*_*vid 3 .net asp.net-mvc spring.net spring-aop

我尝试添加记录,以饰有一个属性的方法使用Spring.Net AOP的.

第1步:引用'Spring.Core','Spring.Aop','Common.Logging'

第2步:建议:

using AopAlliance.Intercept;

namespace MyApp.Aspects
{
    public class LoggingAdvice : IMethodInterceptor
    {
      public object Invoke(IMethodInvocation invocation)
      {
        //todo: log started
        object rval = invocation.Proceed();
        return rval;
        //todo: log finished
      }
    }
}
Run Code Online (Sandbox Code Playgroud)

第3步:创建属性:

using System;

namespace MyApp.Aspects
{
  public class LoggingAttribute : Attribute
  {
  }
}
Run Code Online (Sandbox Code Playgroud)

第4步:编辑web.config

<configuration>
  <configSections>
    <sectionGroup name="spring">
      <section name="context" type="Spring.Context.Support.ContextHandler, Spring.Core" />
      <section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />
    </sectionGroup>
  </configSections>

  <spring>
    <context>
      <resource uri="config://spring/objects" />
    </context>

    <objects xmlns="http://www.springfrmework.net">

      <object id="loggingAdvice" type="MyApp.Aspects.LoggingAdvice, MyApp"></object>
      <object id="loggingAdvisor" type="Spring.Aop.Support.DefaultPointcutAdvisor, Spring.Aop">
        <property name="Advice" ref="loggingAdvice" />
      </object>

      <object type="Spring.Aop.Framework.AutoProxy.AttributeAutoProxyCreator, Spring.Aop">
        <property name="AttributeTypes" value="MyApp.Aspects.LoggingAttribute"/>
        <property name="InterceptorNames" value="loggingAdvisor"/>
      </object>

    </objects>
  </spring>
</configuration>
Run Code Online (Sandbox Code Playgroud)

第5步:使用属性装饰方法:

using System.Web.Mvc;

namespace MyApp.Controllers
{
  public class MyController : Controller
  {
    [Logging]
    public ActionResult DoStuff()
    {
      //todo: implement
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

建议永远不会触发.我错过了什么?

Mar*_*ijn 7

这与创建控制器然后实际调用DoStuff()它的事实有关.控制器显然没有自己的代理,因此调用DoStuff()不会被Spring.Net AOP截获.

正如托克森在他的回答中提到的那样,你必须从春天开始接收控制器,否则就不会发生拦截.我假设您在这里使用spring mvc支持来创建控制器,但是这并没有从您的问题中清楚地显示出来并且您可能已将其删除.

如何拦截MVC 3控制器上的动作方法

摘要

请参阅下面的详细信息和示例.

  1. 用一个 InheritanceBasedAopConfigurer
  2. 声明要拦截为虚拟的方法
  3. 配置你的拦截器

Spring的默认拦截机制不起作用......

当向MVC应用程序发出请求时,则从请求URL开始,MVC框架选择控制器.在此控制器上,Execute()调用该方法,该方法又负责调用操作方法.重要的是要意识到始终从控制器内调用操作方法.

Spring.NET aop使用动态编织.默认情况下,在运行时,会为在配置中声明了aop顾问程序的对象创建代理.此代理拦截调用并转发对目标实例的调用.代理接口类(使用proxy-target-type="true")时完成此操作.当目标对象在其上调用一个方法时,它不会通过spring代理执行此操作,并且该方法不会被截获.这就是为什么默认的aop机制不适用于mvc控制器.

......但使用一个InheritanceBasedAopConfigurer诀窍

要拦截对操作方法的调用,您应该使用InheritanceBasedAopConfigurer.这将创建一个基于继承的代理,该代理不会委托给目标对象,而是在调用基类方法之前直接在方法体中添加拦截建议.

请注意,要使此拦截方法起作用,方法必须是虚拟的.

以下xml配置有效:

<!-- 
When not specifying an object id or name, 
spring will assign a name to it like [typename]#[0,1,2,..]  
-->  
<object type="MyApp.Controllers.HomeController, MyApp" 
        singleton="false" />

<object id="myInterceptor" type="Spring.Aop.Support.AttributeMatchMethodPointcutAdvisor, Spring.Aop">
  <property name="Attribute" value="MyApp.MyAttribute, MyApp" />
  <property name="Advice">
    <object type="MyApp.MyAdvice, MyApp" />
  </property>
</object>

<object type="Spring.Aop.Framework.AutoProxy.InheritanceBasedAopConfigurer, Spring.Aop">
  <property name="ObjectNames">
    <list>
      <value>*Controller#*</value>
    </list>
  </property>
  <property name="InterceptorNames">
    <list>
      <value>myInterceptor</value>
    </list>
  </property>
</object>
Run Code Online (Sandbox Code Playgroud)

github上有一个工作示例.它基于支持Spring.Net Mvc3的标准mvc 3应用程序.相关文件是:

参考