2011-11-06 55 views
1

我在学习Spring.Net,并尝试一些简单的操作,但这种操作不起作用。我想记录的任何方法调用饰LogCall使用aop的Spring.net日志记录示例

namespace WpfApplication1 
{ 
    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      Test(); 
      InitializeComponent(); 
     } 

     [LogCall] 
     public void Test() 
     { 
     } 
    } 

    public class LogCallInterceptor : IMethodBeforeAdvice 
    { 
     public void Before(MethodInfo method, object[] args, object target) 
     { 
      Debug.Write(method.Name); 
     } 
    } 

    [Serializable] 
    [AttributeUsage(AttributeTargets.Method)] 
    public class LogCallAttribute : Attribute 
    { 
    } 
} 

而这里的App.config中

<?xml version="1.0" encoding="utf-8"?> 
<configuration> 
    <spring> 
    <objects xmlns="http://www.springframework.net"> 
     <object id="TestLogAdvice" type="Spring.Aop.Support.AttributeMatchMethodPointcutAdvisor, Spring.Aop"> 
     <property name="advice"> 
      <object type="WpfApplication1.LogCallInterceptor, WpfApplication1" /> 
     </property> 
     <property name="attribute" value="WpfApplication1.LogCallAttribute, WpfApplication1" /> 
     </object> 
    </objects> 
    </spring> 
    <runtime> 
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> 
     <dependentAssembly> 
     <assemblyIdentity name="Spring.Core" publicKeyToken="65e474d141e25e07" culture="neutral" /> 
     <bindingRedirect oldVersion="0.0.0.0-1.3.2.40943" newVersion="1.3.2.40943" /> 
     </dependentAssembly> 
     <dependentAssembly> 
     <assemblyIdentity name="Spring.Aop" publicKeyToken="65e474d141e25e07" culture="neutral" /> 
     <bindingRedirect oldVersion="0.0.0.0-1.3.2.40943" newVersion="1.3.2.40943" /> 
     </dependentAssembly> 
    </assemblyBinding> 
    </runtime> 
</configuration> 

我真的很新的这一切,所以我甚至不知道这是否是一个有效的做法。

根据第一个答案,我重新修改了我的例子。还是行不通?我变暖了吗?

namespace WpfApplication1 
{ 
    /// <summary> 
    /// Interaction logic for MainWindow.xaml 
    /// </summary> 
    public partial class MainWindow : Window 
    { 
     public MainWindow() 
     { 
      var someClass = new SomeClass(); 
      someClass.Test(); 
      InitializeComponent(); 
     } 
    } 

    public class SomeClass 
    { 
     [LogCall] 
     public void Test() 
     { 
     } 
    } 

    public class LogCallInterceptor : IMethodBeforeAdvice 
    { 
     public void Before(MethodInfo method, object[] args, object target) 
     { 
      Debug.Write(method.Name); 
     } 
    } 

    [Serializable] 
    [AttributeUsage(AttributeTargets.Method)] 
    public class LogCallAttribute : Attribute 
    { 
    } 
} 

而且

<?xml version="1.0" encoding="utf-8"?> 
<configuration> 
    <spring> 
    <objects xmlns="http://www.springframework.net"> 
     <object id="TestLogAdvice" type="Spring.Aop.Support.AttributeMatchMethodPointcutAdvisor, Spring.Aop"> 
     <property name="advice"> 
      <object type="WpfApplication1.LogCallInterceptor, WpfApplication1" /> 
     </property> 
     <property name="attribute" value="WpfApplication1.LogCallAttribute, WpfApplication1" /> 
     </object> 
    </objects> 
    <object id="mySomeClass" type="Spring.Aop.Framework.ProxyFactoryObject"> 
     <property name="target"> 
     <object id="mySomeClassTarget" type="WpfApplication1.SomeClass"/> 
     </property> 
     <property name="interceptorNames"> 
     <list> 
      <value>TestLogAdvice</value> 
     </list> 
     </property> 
    </object> 
    </spring> 
    <runtime> 
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> 
     <dependentAssembly> 
     <assemblyIdentity name="Spring.Core" publicKeyToken="65e474d141e25e07" culture="neutral" /> 
     <bindingRedirect oldVersion="0.0.0.0-1.3.2.40943" newVersion="1.3.2.40943" /> 
     </dependentAssembly> 
     <dependentAssembly> 
     <assemblyIdentity name="Spring.Aop" publicKeyToken="65e474d141e25e07" culture="neutral" /> 
     <bindingRedirect oldVersion="0.0.0.0-1.3.2.40943" newVersion="1.3.2.40943" /> 
     </dependentAssembly> 
    </assemblyBinding> 
    </runtime> 
</configuration> 
+0

我已经更新了我的答案,你越来越近了。 – Marijn

+0

您的xml中存在错误:应该移动。 – Marijn

+0

如果这是你的完整app.config,它也不会工作,我会在我的答案下面写一个注释。 – Marijn

回答

3

您正在使用Spring AOP的建立记录,这是一种有效的方法,新的app.config。有几件事你必须考虑:

春天AOP使用动态代理用(日志记录)建议装饰类。此代理拦截对您的对象的调用并应用日志记录建议。在你的课堂上,你可以拨打Test的方法从以内的这个课程本身。这样动态代理就不会拦截这个调用,也不会发生日志记录。

从您的配置中,我看到您定义了需要运行的建议(您的LogCallInterceptor)和哪里(与您的属性匹配的方法),但我没有看到您定义代理工厂的位置。 Spring必须创建一个代理,并且必须告诉它在哪里做。

aop quickstart是了解如何做到这一点的好地方。事实上,第一个例子就是一个日志记录例子,它非常适用于你的问题。我猜在阅读快速入门的第一部分(第38.2.1章)之后,你会知道该怎么做才能使其工作。弹簧AOP是一种强大的技术,但起初可能有点难以掌握。你已经很好了。

编辑1

我看你已经更新了你的问题。我想,你几乎就在那里。

现在您正在直接从代码创建SomeClass实例。这样,Spring再也没有机会创建它的代理。你必须委派的SomeClass 创立到Spring容器:

public MainWindow() 
{ 
    // normally speaking, we should not create the container here, 
    // but that's another subject 
    var ctx = ContexRegistry.GetContext(); // init spring container 
    var someClass = (SomeClass) ctx["mySomeClass"]; 
    someClass.Test(); 
    InitializeComponent(); 
} 

这样,someClass将持有的代理,而不是目标。

之后,还有一个问题(hint)。

编辑2

Your're Test方法有可能是虚拟的,否则弹簧不能创建一个继承基于代理。 (或者你的类必须实现一个或多个接口)。

配置使用自动代理

下app.config中使用一个DefaultAdvisorAutoProxyCreator。这将确保您不必为要应用日志顾问的每个课程创建代理工厂。 DefaultAdvisorAutoProxyCreator将找到所有包含LogCallAttribute的对象,并为它们创建代理。

<?xml version="1.0" encoding="utf-8"?> 

<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.springframework.net"> 

     <object id="TestLogAdvice" type="Spring.Aop.Support.AttributeMatchMethodPointcutAdvisor, Spring.Aop"> 
     <property name="advice"> 
      <object type="q8029460.LogCallInterceptor, q8029460" /> 
     </property> 
     <property name="attribute" value="q8029460.LogCallAttribute, q8029460" /> 
     </object> 

     <object id="ProxyCreator" type="Spring.Aop.Framework.AutoProxy.DefaultAdvisorAutoProxyCreator, Spring.Aop"/> 

     <object id="mySomeClass" type="q8029460.MyClass, q8029460" /> 

    </objects> 
    </spring> 

</configuration> 
+0

阅读快速入门后,我可以看到代理的功能。我必须为每个使用此属性的类声明代理吗? –

+0

这是一种方法,但您也可以创建一个'AutoProxy'。我建议你先试着让它为一个班级工作,然后找出更多关于'AutoProxy'的信息。例如,我的这个答案使用了一个自动代理:http://stackoverflow.com/questions/6658074/how-can-i-spring-net-inject-in-to-methods/6707396#6707396 – Marijn

+0

关于'AutoProxy ':http://www.springframework.net/doc-latest/reference/html/aop.html#aop-autoproxy – Marijn