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方法。
执行后通知没有设定通知过滤中没有涉及到,所以所有拦截到的方法都会出现。