如果我使用Spring AOP横切关注点+ log4net进行日志记录,如何结束单例对象队列
本文关键字:何结束 记录 结束 队列 对象 单例 日志 Spring AOP log4net 关注点 | 更新日期: 2023-09-27 18:12:34
我有一个应用程序,使用Spring。AOP库应用代理-对象来记录程序的方法做了什么(我使用xml-configuration)。在我使用log4net用Spring记录消息之前。AOP(简化类):
public class CommandLoggingAdvice : IMethodInterceptor
{
// here I get an instance of log4net
private ILog _Logger = null;
protected ILog Logger
{
_Logger = LogManager.GetLogger("Logger1");
}
public object Invoke(IMethodInvocation invocation)
{
Logger1.Info("Now we enter to method");
// here i call the method
object returnValue = invocation.Proceed();
Logger1.Info("Now we exit from method");
return returnValue;
}
}
但是有一个问题:我需要使用一个消息队列,它应该在独立的线程中工作,以将程序负载分配给几个线程
这是一个新的春天。AOP类:
public class CommandLoggingAdvice : IMethodInterceptor
{
private static ProducerConsumerClass LoggingQueue = ProducerConsumerClass.Instance;
public object Invoke(IMethodInvocation invocation)
{
LoggingQueue.AddTask("Now we enter to method");
// here I call the method
object returnValue = invocation.Proceed();
LoggingQueue.AddTask("Now we exit from method");
return returnValue;
}
}
/// <summary>
/// ProducerConsumerClass implements:
/// - SingleTon-object, Producer/Consumer queue (queue is a FIFO BlockingCollection) - I need this class to process all messages, which come from CommonLoggingAdvice class. The reason is that I need to do it in independent thread (.IsBackground = false)
/// - This version of Singleton class is threadsafe
/// </summary>
public sealed class ProducerConsumerClass : IDisposable
{
// here Iget an instance of log4net
private ILog _Logger = null;
protected ILog Logger
{
_Logger = LogManager.GetLogger("Logger1");
}
private BlockingCollection<string> tasks = new BlockingCollection<string>();
private static volatile ProducerConsumerClass _instance;
private static object locker = new object();
Thread worker;
private ProducerConsumerClass()
{
worker = new Thread(Work);
worker.Name = "Queue thread";
worker.IsBackground = false;
worker.Start();
}
public static ProducerConsumerClass Instance
{
get
{
if (_instance == null)
{
lock (locker)
{
if (_instance == null)
{
_instance = new ProducerConsumerClass();
}
}
}
return _instance;
}
}
public void AddTask(string task)
{
tasks.Add(task);
}
// now this is unused method
// I need to call this method somehow at the end of program, but cross-cutting concern doesn't allow to do it straightahead
public void Dispose()
{
tasks.CompleteAdding();
worker.Join();
tasks.Dispose();
}
void Work()
{
while (true)
{
string task = null;
if (!tasks.IsCompleted)
{
Thread.Sleep(1000);
task = tasks.Take();
Logger1.Info(worker.Name + " " + task );
}
else
{
return;
}
}
}
}
所以这个类总是在运行("worker"线程也是如此);如果"tasks"为空,- tasks.Take()
强制"worker"线程暂停,直到使用tasks.Add()
添加一些东西。但是当程序的所有功能都结束了,我需要退出程序-"任务"是空的,"工人"被暂停-所以我不能退出无限循环=>程序永远不会结束。
只要春天。AOP类是横切的,它们自动应用,我不知道如何告诉"工作"线程(方法Work()
),它应该完成(CompleteAdding()
方法,或Dispose()
)。
你能帮我解决这个问题吗?或者告诉我其他方法来做我需要的吗?
- Spring的
- 横切关注点。用于日志记录的AOP 在独立线程中使用队列(或生产者/消费者模式)的单例类的线程安全实现,它的存在时间与应用程序的存在时间一样长,甚至更长一点:直到队列为空。
您可以使用一个独立的线程在队列中写入日志。使用锁来解决你对队列写入的需求