使用 aop 的 Spring.net 日志示例 [英] Spring.net Logging Example using aop

查看:33
本文介绍了使用 aop 的 Spring.net 日志示例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在学习 Spring.Net 并且正在尝试一些简单的东西,但这是行不通的.我想记录任何用 LogCall

I'm learning Spring.Net and am trying something simple, which is not working. I want to log any method calls decorated with 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

And here's the 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>

我对这一切真的很陌生,所以我什至不确定这是否是一种有效的方法.

I'm really new to all this so I'm not even sure if this is a valid approach.

基于第一个答案,我重新编写了示例.还是行不通?我暖和了吗?

Based on the first answer, I reworked my example. Still not working? Am I getting warm?

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

And the new 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>

推荐答案

您正在使用 spring aop 设置日志记录,这是一种有效的方法.您必须考虑以下几点:

You are using spring aop to set up logging, and this is a valid approach. There are a couple of things you have to consider:

Spring AOP 使用一个动态代理来装饰一个带有(日志)通知的类.此代理拦截对您的对象的调用并应用日志记录建议.在您的类中,您从类本身的内部 调用Test 方法.这样动态代理就永远不会拦截调用,也不会发生日志记录.

Spring AOP uses a dynamic proxy to decorate a class with (logging) advices. This proxy intercepts calls to your object and applies the logging advice. In your class, you call the Test method from within the class itself. This way the dynamic proxy can never intercept the call and no logging will take place.

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

From your config I read that you define which advice has to run (your LogCallInterceptor) and where (methods matching your attribute), but I don't see where you define your proxy factory. Spring has to create a proxy and you have to tell it where to do it.

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

The aop quickstart is a good place to find out how to do this. In fact, one of the first examples is a logging example, which is very applicable to your question. I'm guessing that after reading the first part of the quickstart (chapter 38.2.1.) you'll know what to do to get this working.

Spring AOP 是一种强大的技术,但一开始可能有点难以掌握.你已经在路上了.

Spring AOP is a powerful technique, but can be a bit hard to master at first. You're well on your way already.

编辑 1

我看到你更新了你的问题.你快到了,我想.

I see you've updated your question. You're almost there, I think.

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

Now you're creating a SomeClass instance directly from code. This way, Spring again doesn't get a chance to create it's proxy. You have to delegate the creation of SomeClass to the spring container:

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 将持有代理而不是目标.

This way, someClass will hold the proxy instead of the target.

此后,还有一个问题(提示).

After this, there's one problem remaining (hint).

编辑 2

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

Your're Test method has to be virtual, otherwise spring can't create an inheritance based proxy. (or your class has to implement one or more interfaces).

使用自动代理的配置

以下 app.config 使用 DefaultAdvisorAutoProxyCreator.这将确保您不必为要应用日志顾问的每个类创建代理工厂.DefaultAdvisorAutoProxyCreator 将查找具有 LogCallAttribute 的所有对象并为它们创建代理.

The following app.config uses an DefaultAdvisorAutoProxyCreator. This will make sure you don't have to create a proxy factory for each and every class you want to apply your logging advisor to. The DefaultAdvisorAutoProxyCreator will find all objects with LogCallAttributes and create a proxy for them.

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

这篇关于使用 aop 的 Spring.net 日志示例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆