<二>使用castle.core 简单实现AOP
一、实现方式
- 静态代理:代理模式,装饰器模式。
- 动态代理:利用反射生成动态代理类。
- 特性:利用.netcore框架自带的特性框架做封装。比如:Filter
- Emit: 机器自动生成代理类。比如:castle.core
- 静态编织:在代码编译的时候动态插入代码。
二、Castle.core使用的Emit的方式动态帮助我们生成代理类,不用我们自己去定义一个类来实现代理了。
1、nuget搜索castle.core 并引用
2、使用Castle.core的CreateClassProxy动态生成代理类来实现AOP
- 修改MySqlDBHelper 将show修改为虚方法,新增一个方法show1为非虚方法。
-
public class MySqlDBHelper: IDBHelper { public virtual void show() { Console.WriteLine("I am Mysql"); } public void show1() { Console.WriteLine("I am Mysql1"); } }
- 新建一个CastleAOPProxy类来作为Castle.core的操作类
-
public class CastleAOPProxy { public static void show() { ProxyGenerator generator = new ProxyGenerator(); MyInterceptor interceptor=new MyInterceptor (); IDBHelper dbhelper = generator.CreateClassProxy<MySqlDBHelper>(interceptor); Console.WriteLine("生成的类型时:{0}", dbhelper.GetType()); dbhelper.show();
dbhelper.show1(); } } - 再新建一个类实现Castle.core的标准织入类StandardInterceptor的钩子方法
-
public class MyInterceptor:StandardInterceptor { /// <summary> /// 调用前拦截 /// </summary> /// <param name="invocation"></param> protected override void PreProceed(IInvocation invocation) { Console.WriteLine("调用前拦截,调用方法:" + invocation.Method.Name); base.PerformProceed(invocation); } /// <summary> /// 拦截的方法返回时调用 /// </summary> /// <param name="invocation"></param> protected override void PreformProceed(IInvocation invocation) { Console.WriteLine("调用方法返回时拦截,调用方法:" + invocation.Method.Name); base.PostProceed(invocation); } /// <summary> /// 调用后拦截 /// </summary> /// <param name="invocation"></param> protected override void PostProceed(IInvocation invocation) { Console.WriteLine("调用后拦截,调用方法:" + invocation.Method.Name); base.PreProceed(invocation); } }
- 在Program调用一下看看
-
CastleAOPProxy.show();
看看上面的执行结果,动态生成的代理类叫做MysqlDBHelperProxy了不是MysqlDBHelper,也就是说Castle给我们动态生成了代理类,并把MyInterceptor里面的钩子方法植入了。但是Show1没有运行钩子方法,也就是说ProxyGenerator只会对虚方法启作用。
3、使用Castle.core的CreateInterfaceProxyWithTargetInterface动态生成代理类来实现AOP
- 在CastleAOPProxy中新增一个ShowInterface的方法
-
public static void ShowInterface() { ProxyGenerator generator = new ProxyGenerator(); MyInterceptor interceptor = new MyInterceptor(); IDBHelper dbhelper = new MySqlDBHelper(); IDBHelper dbhelperProxy = generator.CreateInterfaceProxyWithTargetInterface<IDBHelper>(dbhelper,interceptor); Console.WriteLine("生成的类型时:{0}", dbhelper.GetType()); dbhelperProxy.show(); dbhelperProxy.show1(); }
- 修改program中的调用方法
-
CastleAOPProxy.ShowInterface();
从上面结果看,不管是虚方法还是其他方法都可以实现了AOP。以上是两种使用代理动态织入的方式。
4、使用特性+Castle.core的CreateInterfaceProxyWithTargetInterface来实现AOP
- 添加一个新的interceptor类叫MyAttributeInterceptor,通过对方式是否加了LogAttribute类型进行过滤是否执行植入逻辑
-
public class MyAttributeInterceptor : StandardInterceptor { /// <summary> /// 调用前拦截 /// </summary> /// <param name="invocation"></param> protected override void PerformProceed(IInvocation invocation) { base.PerformProceed(invocation); if (!IsLog(invocation)) return; Console.WriteLine("调用时拦截,调用方法:" + invocation.Method.Name); } /// <summary> /// 拦截的方法返回时调用 /// </summary> /// <param name="invocation"></param> protected override void PostProceed(IInvocation invocation) { base.PostProceed(invocation); if (!IsLog(invocation)) return; Console.WriteLine("调用后拦截,调用方法:" + invocation.Method.Name); } /// <summary> /// 调用后拦截 /// </summary> /// <param name="invocation"></param> protected override void PreProceed(IInvocation invocation) { base.PreProceed(invocation); if (!IsLog(invocation)) return; Console.WriteLine("调用前拦截,调用方法:" + invocation.Method.Name); } private bool IsLog(IInvocation invocation) { var method = invocation.Method; if (method.IsDefined(typeof(LogAttribute), true)) { return true; } return false; } }
- 添加一个特性LogAttribute
-
public class LogAttribute:Attribute { }
- 给IDBHelper的某个方法加上Log的特性
-
public interface IDBHelper { [Log] void show(); void show1(); }
- 在CastleAOPProxy中新增一个ShowAttibuteInterface的方法
-
public static void ShowAttibuteInterface() { ProxyGenerator generator = new ProxyGenerator(); MyAttributeInterceptor interceptor = new MyAttributeInterceptor(); IDBHelper dbhelper = new MySqlDBHelper(); IDBHelper dbhelperProxy = generator.CreateInterfaceProxyWithTargetInterface<IDBHelper>(dbhelper, interceptor); Console.WriteLine("生成的类型时:{0}", dbhelper.GetType()); dbhelperProxy.show(); dbhelperProxy.show1(); }
- 在program中调用该方法
-
CastleAOPProxy.ShowAttibuteInterface();
如上图所示,添加了Log特性的Show方法显示了MyAttribute中的钩子方法。而show1没有添加的并没有显示。