【问题标题】:Spring.net Logging Example using aop使用 aop 的 Spring.net 日志记录示例
【发布时间】:2011-11-07 14:13:51
【问题描述】:

我正在学习 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>

【问题讨论】:

  • 我已经更新了我的答案,你已经接近了。
  • 您的 xml 中有一个错误: 应该被移动。
  • 如果这是你完整的 app.config,它也不起作用,我会在我的答案下面写一个注释。

标签: logging aop spring.net


【解决方案1】:

您正在使用 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 会找到所有带有LogCallAttributes 的对象并为它们创建一个代理。

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

【讨论】:

  • 阅读快速入门后,我可以看到代理的作用。我是否必须为每个使用该属性的类声明一个代理?
  • 这是一种方法,但您也可以创建一个AutoProxy。我建议你首先尝试让它为一个班级工作,然后了解更多关于AutoProxy 的信息。例如,我的这个答案使用自动代理:stackoverflow.com/questions/6658074/…
  • 啊,灯泡时刻。我回到创建代理工厂并添加建议的示例。然后获取代理并执行测试。我添加了一个 ISomeClass 接口来使用组合代理。现在说得通了。感谢您的帮助。
  • 太棒了!您也可以将 Test 方法设为虚拟,以便 spring 可以创建基于继承的代理。
猜你喜欢
  • 1970-01-01
  • 2018-04-13
  • 1970-01-01
  • 2012-11-04
  • 2012-09-30
  • 1970-01-01
  • 1970-01-01
  • 2013-03-22
  • 1970-01-01
相关资源
最近更新 更多