This has to do with the fact that the controller is created and then actually calls DoStuff()
on it self. The controller obviously does not hold a proxy to itself and therefore the call to DoStuff()
does not get intercepted by Spring.Net AOP.
As tobsen mentions in his answer, you will have to get the controller from spring, otherwise interception will not take place. I assume you're using spring mvc support here to create controllers, but this does not clearly show from your question and you might have left it out.
How to intercept action methods on MVC 3 controllers
Summary
See below for details and an example.
- Use an
InheritanceBasedAopConfigurer
- Declare methods you want to intercept as virtual
- Configure your interceptors
Spring's default interception mechanism does not work ...
When a request is made to an MVC app, then from the request url a controller is chosen by the MVC framework. On this controller, the Execute()
method is called, which in turn is responsible for invoking the action methods. It is important to realize that action methods are always called from within the controller.
Spring.NET aop uses dynamic weaving. By default, at runtime a proxy is created for objects for which aop advisors are declared in the configuration. This proxy intercepts calls and forwards calls to the target instance. This is done when proxying interfaces and classes (using proxy-target-type="true"
). When the target object invokes a method on it self, it will not do this through the spring proxy and the method does not get intercepted. This why the default aop mechanism doesn't work for mvc controllers.
... but using an InheritanceBasedAopConfigurer
does the trick
To intercept calls on action methods, you should use an InheritanceBasedAopConfigurer
. This will create an inheritance based proxy that does not delegate to a target object, instead interception advice is added directly in the method body before invoking the base class method.
Note that for this interception method to work, the methods have to be virtual.
The following xml config works:
<!--
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>
A working example is available on github. It is based on a standard mvc 3 application with Spring.Net Mvc3 support. Relevant files are:
References