在一个夜黑风高的深夜,我发现我的程序少了一样东西,一个用来记录程序运行过程和状态的东西。呃,是日志系统。所以我去网上搜索了一番,发现有好多开源的日志系统:log4cplus、log4C、log4cxx等等。经过比较我觉得log4cplus比较符合我的口味,因此下载了log4cplus的源代码。
对刚入手的log4cplus一筹莫展,据网上的教程说log4cplus具有以下几个元素:hierarchy、appender、logger、layout、filter、loglevel和loglog等等。另外log4cplus支持读取配置文件来动态创建各个元素。这的却很诱人,但是网上的教程我看的不太懂,并且不能让我深入理解。所以我决定去阅读源代码,一开始真的很痛苦,因为你不知道这是什么,这和这又有什么关系。还好有调试器在,经过多次的单步跟踪和记录(把已经知道的记录下来),总算摸清楚了一点来龙去脉。
先来说说让人诟病的loglevel吧,log4cplus对自定义loglevel的支持的却让人蛋疼。首先你要实现两个方法:StringToLogLevelMethod和LogLevelToStringMethod,然后把这两个方法push到LogLevelManager中的单向链表。这就意味着当LogLevelManager需要对loglevel和string之间互相转换时必须进行遍历整个链表,效率就谈不上高了。
我在阅读log4cplus源代码的时候发现某些实现真的让人牙痛,比如LoggerImpl和Logger之间的关系。虽然说Logger是LoggerImpl的使用代理,但是在管理LoggerImpl的使用权上实在是晦涩难懂,比如Logger重载的赋值操作符,你会发现它的实现是使用swap。如果你不清楚Logger的具体作用,那么很容易在这里被迷惑。只有仔细的观察和研究后才能理解这个重载的赋值操作符其实是利用了一个临时的Logger对象,这个临时对象拷贝构造传入的Logger对象(即为赋值操作符右边的对象),然后使用swap和自身对象(this)交换LoggerImpl对象(直接指针交换),这样自身对象(this)的LoggerImpl被交换到了临时的Logger对象内部,而临时Logger对象的LoggerImpl(其实就是作为参数传入的Logger对象的LoggerImpl)交换给了自身对象(this)。最后临时Logger对象结束作用域而被销毁,意味着内部LoggerImpl被减引用一次。
现在你知道阅读这log4cplus源代码的痛苦了吧,你不知道上面这一段描述Logger的赋值操作在说什么,没关系,我已经决定仿制log4cplus,在实现上更简单明了。
等有空再说说我的实现方式。