Spring.Net的切入点、AOP通知过滤器

本文详细介绍了Spring.NET中的AOP过滤器概念及其应用,包括方法名称匹配、正则表达式匹配、特性匹配及自定义动态过滤器等,并通过实战演示了名称过滤器和特性过滤器的具体使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Spring.Net除了上一篇文章写的IOC、AOP、属性注入、构造函数注入之外,还有切入点(过滤器),比如方法名字过滤、正则表达式过滤、特性过滤以及自定义动态切入点。

 

今天记录一下切入点或者说过滤器,先讲概念,文章最后上实战演示。

本文章涉及的演示实例下载地址:https://download.youkuaiyun.com/download/xuefuruanjian/11390775

 

常规AOP是拦截到的所有方法都会被通知(除了虚方法的AOP),但有时候我们只想某几个方法有通知就好了,怎么办,这时就需要过滤点,即通知的切入点。所以需要一些合适匹配的过滤器。

Spring.Net中,只要实现IPointcutAdvisor接口的都可以做为过滤器,Spring.Aop.Support命名空间下有不少,下面举几个常用的例子:

1、方法名称匹配过滤器

如下代码,使用程序集Spring.Aop中的Spring.Aop.Support.NameMatchMethodPointcutAdvisor类可进行方法名字过滤。

2、正则表达式匹配过滤器

使用程序集Spring.Aop中的Spring.Aop.Support.RegularExpressionMethodPointcutAdvisor,Spring.Aop.Support.SdkRegularExpressionMethodPointcut 

<object id="settersAndAbsquatulatePointcut"
    type="Spring.Aop.Support.SdkRegularExpressionMethodPointcut, Spring.Aop">
  <property name="patterns">
    <list>
      <value>.*set.*</value>
      <value>.*absquatulate</value>
    </list>
  </property>
</object>

 

<object id="settersAndAbsquatulateAdvisor"
    type="Spring.Aop.Support.RegularExpressionMethodPointcutAdvisor, Spring.Aop">
  <property name="advice">
    <ref local="objectNameOfAopAllianceInterceptor"/>
  </property>
  <property name="patterns">
    <list>
      <value>.*set.*</value>
      <value>.*absquatulate</value>
    </list>
  </property>
</object>

3、特性过滤器

使用程序集Spring.Aop中的Spring.Aop.Support.AttributeMatchMethodPointcutAdvisor

<object id="aroundAdvisor" type="Spring.Aop.Support.AttributeMatchMethodPointcutAdvisor, Spring.Aop">
  <property name="Advice">
    <object type="Spring.Net.Example.Aspects.LogBeforeAdvice,Spring.Net.Example" />
  </property>
  <property name="Attribute" value="Spring.Net.Example.AttributeExtend.LogAttribute, Spring.Net.Example" />
</object>

4、自定义动态切入点,或者说自定义过滤器,暂时没有实际使用,使用后再补。

 

以下为使用名称过滤器和特性过滤器的演示实例,请参考:

配置文件:

      <!--拦截通知-->
      <object id="beforeAdvice" type="Spring.Net.Example.Aspects.LogBeforeAdvice,Spring.Net.Example"/>
      <object id="aroundAdvice" type="Spring.Net.Example.Aspects.LogAroundAdvice,Spring.Net.Example"/>
      <object id="afterAdvice" type="Spring.Net.Example.Aspects.LogAfterAdvice,Spring.Net.Example"/>
      <object id="exceptAdvice" type="Spring.Net.Example.Aspects.LogExceptAdvice,Spring.Net.Example"/>

      <!--名称过滤器-->
      <object id="aroundAdvisor" type="Spring.Aop.Support.NameMatchMethodPointcutAdvisor, Spring.Aop">
        <!--通知过滤-->
        <property name="Advice">
          <object type="Spring.Net.Example.Aspects.LogAroundAdvice,Spring.Net.Example" />
        </property>
        <!--方法名称过滤-->
        <property name="MappedNames">
          <list>
            <value>*Show</value>
          </list>
        </property>
      </object>

      <!--特性过滤器-->
      <object id="beforeAdvisor" type="Spring.Aop.Support.AttributeMatchMethodPointcutAdvisor, Spring.Aop">
        <property name="Advice">
          <object type="Spring.Net.Example.Aspects.LogBeforeAdvice,Spring.Net.Example" />
        </property>
        <property name="Attribute" value="Spring.Net.Example.AttributeExtend.LogAttribute, Spring.Net.Example" />
      </object>
      
      <!--测试对象-->
      <object id="aopStudentI" type="Spring.Aop.Framework.ProxyFactoryObject">
        <property name="Target">
          <object type="Spring.Net.Example.Commands.StudentI, Spring.Net.Example" />
        </property>
        <property name="InterceptorNames">
          <list>
            <!--<value>beforeAdvice</value>-->
            <value>beforeAdvisor</value><!--使用特性过滤器-->
            <!--<value>aroundAdvice</value>-->
            <value>aroundAdvisor</value><!--使用名称过滤器-->
            <value>afterAdvice</value>
            <value>exceptAdvice</value>
          </list>
        </property>
      </object>

AOP通知类:

namespace Spring.Net.Example.Aspects
{

    public class LogBeforeAdvice : IMethodBeforeAdvice
    {
        public void Before(MethodInfo method, object[] args, object target)
        {
            Console.WriteLine("[执行前通知]拦截的方法名—>" + method.Name);
            Console.WriteLine("[执行前通知]目标—>" + target);
            Console.WriteLine("[执行前通知]参数—>");
            if (args != null)
            {
                foreach (object arg in args)
                {
                    Console.WriteLine("\t: " + arg);
                }
            }
        }
    }



    public class LogAroundAdvice : IMethodInterceptor
    {
        public object Invoke(IMethodInvocation invocation)
        {
            Console.Out.WriteLine(String.Format("[环绕通知]拦截的方法名—> '{0}'", invocation.Method.Name));

            object returnValue = invocation.Proceed();

            Console.Out.WriteLine(String.Format("[环绕通知]返回—> '{0}'", returnValue));

            return returnValue;
        }
    }



    public class LogAfterAdvice : IAfterReturningAdvice
    {
        public void AfterReturning(object returnValue, MethodInfo method, object[] args, object target)
        {
            Console.Out.WriteLine("[执行后通知]拦截的方法名—>" + method.Name);
            Console.Out.WriteLine("[执行后通知]目标—>" + target);
            Console.Out.WriteLine("[执行后通知]参数—>");
            if (args != null)
            {
                foreach (object arg in args)
                {
                    Console.Out.WriteLine("\t: " + arg);
                }
            }
            Console.Out.WriteLine("[执行后通知]返回值—>" + returnValue);
        }
    }



    public class LogExceptAdvice : IThrowsAdvice
    {
        public void AfterThrowing(Exception ex)
        {
            Console.Error.WriteLine($"异常—>{ex.Message}");
        }
    }
}

特性类:

namespace Spring.Net.Example.AttributeExtend
{
    public class LogAttribute : Attribute
    {
        public LogAttribute()
        {
        }
    }
}

实体类:


namespace Spring.Net.Example.Commands
{

    public interface IAttrFilterStudent
    {
        void Show();
        void ShowPhone();
        void Write();
    }


    public class StudentI : IAttrFilterStudent
    {
        public UserInfo Friend { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }

      
        public void Show()
        {
            Console.WriteLine($"我是Show方法");
        }

        public void ShowPhone()
        {
            Console.WriteLine($"我是ShowPhone方法");
        }

        [Log]
        public virtual void Write()
        {
            Console.WriteLine($"我是Write方法");
        }
    }
}

 上层调用:

    class Program
    {
        static void Main(string[] args)
        {


            //*****************AOP通知过滤器********************************

            Console.WriteLine("--------");

            IApplicationContext context = ContextRegistry.GetContext();
            IAttrFilterStudent interfaceCommand = (IAttrFilterStudent)context["aopStudentI"];
            interfaceCommand.Show();

            Console.WriteLine("--------");
            interfaceCommand.ShowPhone();

            Console.WriteLine("--------");
            interfaceCommand.Write();


            Console.ReadLine();

        }
    }

结果:

执行前通知和环绕通知在通知的过滤条件中,所以没匹配上的两个通知都没有,如ShowPhone方法。

执行后通知没有设定通知过滤中没有涉及到,所以所有拦截到的方法都会出现。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值