前言:
最近接手了一个二手项目,该项目的最大特点就是 拥有众多的上下游 外部产品或项目。运维时总会时不时出现各种异常(有系统本身的,有业务的),这时要求能最快定位到问题点。这就需要有详细的日志流来支撑这样的工作。
翻开代码查看,记录日志的模式主要靠埋点(如:访问某某ESB服务花了多少时间,返回值是多少)。做为一个老司机,非常痛恨这种埋点,因为没有做到日志与业务解耦。而且违背功能单一原则。
解决思路
当然想到了AOP,让我们的业务代码跟我们的运维代码 和一些非业务流程代码实现解耦。
这时候想到了 Castle Windsor,Castle Windsor 提供了IOC容器实践,同时支持AOP思想。
实践
Nuget 安装 Castle.Core 和 Castle.Windsor
1、定义我们的业务抽象接口(契约)
public interface IMessageService
{
IEnumerable
}
2、定义业务实现类
public IEnumerable
{
rowCount = 20;
List
messages.Add(new MessageEntity() { CreateDateTime = DateTime.Now , Id = Guid.NewGuid() , Title = "001" });
messages.Add(new MessageEntity() { CreateDateTime = DateTime.Now, Id = Guid.NewGuid(), Title = "002" });
messages.Add(new MessageEntity() { CreateDateTime = DateTime.Now, Id = Guid.NewGuid(), Title = "003" });
messages.Add(new MessageEntity() { CreateDateTime = DateTime.Now, Id = Guid.NewGuid(), Title = "004" });
messages.Add(new MessageEntity() { CreateDateTime = DateTime.Now, Id = Guid.NewGuid(), Title = "005" });
messages.Add(new MessageEntity() { CreateDateTime = DateTime.Now, Id = Guid.NewGuid(), Title = "006" });
messages.Add(new MessageEntity() { CreateDateTime = DateTime.Now, Id = Guid.NewGuid(), Title = "007" });
messages.Add(new MessageEntity() { CreateDateTime = DateTime.Now, Id = Guid.NewGuid(), Title = "008" });
messages.Add(new MessageEntity() { CreateDateTime = DateTime.Now, Id = Guid.NewGuid(), Title = "009" });
messages.Add(new MessageEntity() { CreateDateTime = DateTime.Now, Id = Guid.NewGuid(), Title = "010" });
return messages;
}
3、编写日志记录器
public class LogInterceptor : IInterceptor //必须实现这个接口
{
public void Intercept(IInvocation invocation)
{
var methodName = invocation.Method.Name;
try
{
Console.WriteLine(string.Format("Entered Method:{0}, Arguments: {1}", methodName, string.Join(",", invocation.Arguments)));
invocation.Proceed(); //这里是业务类的方法
Console.WriteLine(string.Format("Sucessfully executed method:{0}", methodName));
}
catch (Exception e)
{
Console.WriteLine(string.Format("Method:{0}, Exception:{1}", methodName, e.Message));
throw;
}
finally
{
Console.WriteLine(string.Format("Exiting Method:{0}", methodName));
}
}
}
4、编写注册类(注册我们的业务抽象的实现,以及绑定具体的插片(如:日志))
public class ComponentRegistration : IRegistration
{
public void Register(IKernelInternal kernel)
{
kernel.Register(
Component.For
kernel.Register(Component.For
}
}
5、初始化我们的依赖,在项目启动时调用
DependencyResolver.Initialize();
public class DependencyResolver
{
private static IWindsorContainer _container;
//Initialize the container
public static void Initialize()
{
_container = new WindsorContainer();
_container.Register(new ComponentRegistration());
}
//Resolve types
public static T For
{
return _container.Resolve
}
}
总结
当然ComponentRegistration 里的内容非常推荐搞到配置文件里。毕竟在代码里写死是一件非常糟糕的事情。
Castle.Windsor 还有非常丰富的注入方式,可以上网搜。这里只是说明对IOC和AOP的支持。