Spring.net使用aop记录示例

时间:2011-11-06 18:49:40

标签: logging aop spring.net

我正在学习Spring.Net,我正在尝试一些简单的东西,但是没有用。我想记录用LogCall

装饰的任何方法调用
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
    {
    }
}

新的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>
    <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>

1 个答案:

答案 0 :(得分:3)

您正在使用spring aop来设置日志记录,这是一种有效的方法。有几件事你需要考虑:

Spring AOP使用动态代理来装饰具有(日志记录)建议的类。此代理拦截对您的对象的调用并应用日志记录建议。在您的课程中,您可以在类中调用Test方法。这样,动态代理永远不会拦截调用,也不会进行日志记录。

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

aop quickstart是了解如何执行此操作的好地方。实际上,第一个示例之一是日志示例,它非常适用于您的问题。我猜测在阅读快速入门的第一部分(第38.2.1章)之后,你会知道如何使其发挥作用。

Spring AOP是一种强大的技术,但最初可能有点难以掌握。你已经顺利了。

编辑1

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

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

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

您的Test方法必须是虚拟的,否则spring无法创建基于继承的代理。 (或者你的类必须实现一个或多个接口)。

使用自动代理配置

以下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>