Spring.Net引人注目的AOP(Unobtrusive AOP with Spring.Net)

编程入门 行业动态 更新时间:2024-10-17 23:23:17
Spring.Net引人注目的AOP(Unobtrusive AOP with Spring.Net)

我试图将日志记录添加到使用Spring.Net for AOP 的属性修饰的方法中

第一步:参考'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 } } }

第3步:创建一个属性:

using System; namespace MyApp.Aspects { public class LoggingAttribute : Attribute { } }

第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>

第5步:装饰一个方法的属性为:

using System.Web.Mvc; namespace MyApp.Controllers { public class MyController : Controller { [Logging] public ActionResult DoStuff() { //todo: implement } } }

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

I'm trying to add logging to methods decorated with an attribute using Spring.Net for AOP.

Step 1: Reference 'Spring.Core', 'Spring.Aop', 'Common.Logging'

Step 2: Create an advice:

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 } } }

Step 3: Create an attribute:

using System; namespace MyApp.Aspects { public class LoggingAttribute : Attribute { } }

Step 4: Edit 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>

Step 5: Decorate a method with the attribute:

using System.Web.Mvc; namespace MyApp.Controllers { public class MyController : Controller { [Logging] public ActionResult DoStuff() { //todo: implement } } }

The advice is never triggered. What am I missing?

最满意答案

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

正如tobsen在他的回答中提到的那样,你将不得不从春天得到控制器,否则拦截将不会发生。 我假设你在这里使用spring mvc支持来创建控制器,但是这并没有从你的问题中清楚地显示出来,而你可能已经将它遗漏了。

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

概要

有关详细信息和示例,请参阅下文。

使用InheritanceBasedAopConfigurer 将你想截取的方法声明为虚拟 配置你的拦截器

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

当向MVC应用程序发出请求时,然后从请求url中由MVC框架选择一个控制器。 在该控制器上,调用Execute()方法,该方法负责调用操作方法。 意识到操作方法总是从控制器内部调用是很重要

Spring.NET aop使用动态编织。 默认情况下,在运行时会为配置中声明aop顾问的对象创建代理。 该代理拦截呼叫并将呼叫转发给目标实例。 这是在代理接口和类(使用proxy-target-type="true" )时完成的 。 当目标对象调用它自己的方法时,它不会通过弹簧代理执行此操作,并且该方法不会被拦截 。 这就是为什么默认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>

一个可用的例子在github上可用 。 它基于带有Spring.Net Mvc3支持的标准mvc 3应用程序。 相关文件是:

xml配置 HomeController 属性和拦截器

参考

Spring.net文档:使用基于aop配置器的继承 代理接口 vs 代理类 关于事务拦截的类似问题在这里: Asp.Net MVC Controller:Spring.Net的声明式AOP 。 解决方案可以是将调用委托给注入的服务或使用基于继承的代理,请参阅Mark对上述问题的回答。 在后一种情况下, DoStuff()应该被声明为虚拟的。 spring.net论坛帖子

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:

xml configuration HomeController attribute and interceptor

References

Spring.net docs: proxying interfaces vs proxying classes vs using an inheritance based aop configurer A similar question with regard to transaction interception is here: Asp.Net MVC Controller: declarative AOP with Spring.Net. Solution can be to delegate calls to injected services or to use an inheritance based proxy, see Mark's answer to the question mentioned above. In the latter case DoStuff() should be declared virtual. spring.net forum post

更多推荐

本文发布于:2023-04-28 05:09:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1330330.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:引人注目   Net   Spring   AOP   Unobtrusive

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!