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

it2022-05-05  140

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

 

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

本文章涉及的演示实例下载地址:https://download.csdn.net/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方法。

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


最新回复(0)