需求:咱们须要给已经开发好的服务如这里的UserService,添加额外的执行逻辑,可是又不想破坏原有的服务,如:咱们须要给UserService添加监控逻辑,监控的目的是看UserService服务里的RegUser方法和GetUser方法的执行时间消耗缓存
一、定义1个用户接口app
namespace UnityConfigAOP { public interface IUserService { void RegUser(User user); User GetUser(User user); } }
二、实现用户这个接口性能
namespace UnityConfigAOP { public class UserService:IUserService { public void RegUser(User user) { Console.WriteLine("用户已注册。"); } public User GetUser(User user) { Console.WriteLine("获得用户信息。"); return user; } } }
三、Unity配置文件
3.一、须要引用以下图这5个程序集ui
3.一、Unity.Config配置文件的注册顺序就是额外逻辑的调用顺序,而后才是业务方法自己,可是扩展逻辑能够是业务方法后this
<configuration> <configSections> <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Unity.Configuration"/> <!--Microsoft.Practices.Unity.Configuration.UnityConfigurationSection--> </configSections> <unity> <sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Unity.Interception.Configuration"/> <containers> <container name="aopContainer"> <extension type="Interception"/> <register type="UnityConfigAOP.IUserService,UnityConfigAOP" mapTo="UnityConfigAOP.UserService,UnityConfigAOP"> <interceptor type="InterfaceInterceptor"/> <interceptionBehavior type="UnityConfigAOP.AOPBehavior.MonitorBehavior, UnityConfigAOP"/> </register> </container> </containers> </unity> </configuration>
3.二、接口方法不须要某个AOP扩展怎么办呢?在方法上加个CustomNOAOPAttribute自定义属性,在执行MonitorBehavior类的Invoke方法里用特性input.Target.GetType().IsDefined(typeof(CustomNOAOPAttribute), true)去判断一下spa
3.三、MonitorBehavior监控行为额外逻辑代码pwa
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; using Unity.Interception.InterceptionBehaviors; using Unity.Interception.PolicyInjection.Pipeline; namespace UnityConfigAOP.AOPBehavior { /// <summary> /// 性能监控的AOP扩展 /// </summary> public class MonitorBehavior : IInterceptionBehavior { public IEnumerable<Type> GetRequiredInterfaces() { return Type.EmptyTypes; } public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext) { var type = input.Target.GetType(); string methodName = input.MethodBase.Name; if (type.IsDefined(typeof(CustomNOAOPAttribute), true)) { var method = getNext().Invoke(input, getNext);//后续逻辑执行 return method; } MethodInfo currentMethod = type.GetMethod(methodName); if (currentMethod.IsDefined(typeof(CustomNOAOPAttribute), true))//检查方法有没有定义此属性 { var method = getNext().Invoke(input, getNext);//后续逻辑执行 return method; } Console.WriteLine(this.GetType().Name); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); var methodReturn = getNext().Invoke(input, getNext);//后续逻辑执行 stopwatch.Stop(); Console.WriteLine($"{this.GetType().Name}统计方法{methodName}执行耗时{stopwatch.ElapsedMilliseconds}ms"); return methodReturn; } public bool WillExecute { get { return true; } } } }
四、客户端调用UserService服务3d
namespace UnityConfigAOP { class Program { static void Main(string[] args) { User user = new User() { Name = "David.Meng", Password = "123456" }; //配置UnityContainer IUnityContainer container = new UnityContainer(); ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap(); fileMap.ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "CfgFiles\\Unity.Config"); Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None); UnityConfigurationSection configSection = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName); configSection.Configure(container, "aopContainer"); IUserService userService = container.Resolve<IUserService>(); userService.RegUser(user); userService.GetUser(user); } } }
五、调试代码
执行userService.RegUser(user);代码的时候,并无直接进入到RegUser(User user);方法里面,而是先进到MonitorBehavior类的Invoke方法里,直到执行到getNext().Invoke(input, getNext);这句代码才真正的进入到RegUser(User user);方法里面调试
七、项目截图,咱们能够配置多个AOP行为不光是监控行为,还能够配置日志行为,异常行为,缓存行为等等,以下图所示日志