当前位置: 首页 > news >正文

Log4j被OSGI撞了一下腰

自从n多年前使用log4j起,印象中就没有觉得Log4j有什么太折磨人的问题,稍微复杂些的可能就是扩展自己的Appender。
不过这一次是碰到了一个比较棘手的“麻烦”。这个麻烦并不是因为难,而是遇到之前不曾注意到问题,被Log4j不小心撞了一下腰,还挺酸疼的。
之前使用Log4j非常简单,因为大多都是在同一个ClassLoader或ContextLoader中,所以只需要把log4j.xml或log4j.properties文件仍到classpath中即可(尽量是在某一个lib目录下),因为Log4j的LogManager会自动寻找和配置。当然,尽量不把log4j的配置文件放在jar中,这种做法不便于后期客户维护和更新。
后来apache推出的 commons-logging让这个简单了一些,但无非多配置一个logging.properties文件。
再后来 SLF4J让log操作变的更为简易,只需要动态替换不同的jar包即可轻松实现部署时候的日志处理包的替换。并且支持commons-logging。
于是,在不同的组件包中,在一些需要记录日志的类中,我们一般会用commons-logging的Log类,于是就会在这些类的前面,增加上一行诸如此的代码:
Log log = LogFactory.getLogger(<your_class>);
可如今,我们的Framework面临基于OSGI进行重组,各个组件都变成了plugin。但是,正因为这个osgi的框架存在,让单个classloader变的不再起作用。因为OSGI里面的各个Bundle是有独立的 ClassLoader来进行加载的。
我们总不能在每一个bundler中去放一个log4j.properties文件,这是不现实的。
在javaeye论坛上,也有人讨论过此类问题,但是解决的办法有些简单。参见: http://www.iteye.com/post/333171
虽然可以把log4j做成一个plugin,并把log4j.properties文件放在这个plugin中,利用SLF4J在OSGI环境下动态配置。但这是一个不能采用的方式,并不是技术上实现不了,而是业务上不允许。因为未来客户可能会从update站点更新这些boudles,而且可能还需要手工修改log4j的配置。
于是,想到了利用log4j.configuration这个System Property变量进行控制。Log4j允许你利用这个变量来硬性指定log4j配置文件的URL地址。
System.setProperty("log4j.configuration", "file:///D:/tibco/config/log4j.properties");
好像这个问题解决了哦,但是并没有这么简单。
在我们开发的产品组件中,有很多command命令,每个命令都有一个自己规范的.tra文件来设置环境信息。那么这意味这我们需要在这些.tra文件中都增加一行对这个log4j.configuration变量的声明。
于是 有的开发人员提出,这种方式对客户并不是很友好。我们可以允许客户自己手工设置这个变量来指定所采用log4j配置文件,但我们应该提供默认的,而且这个默认配置是不应该显示的展现出来,所以我们应该在一些主要的组件中利用代码来控制,如果客户没有额外配置的化,那么应该利用代码“透明化”的配置,对客户透明的。当然这个也必须遵循统一的规范,比如默认的log4j配置文件放在某一个默认目录下。
这个想法是好的,而且不难实现,因为利用Log4j自带的Configurator实现类可以很轻松的实现这样的额外配置。
PropertyConfigurator.configure("D:/tibco/config/log4j.properties ");
但是, 很不幸运,我们并没有把所有的command都转换成osgi的方式,有一些因为特殊原因不支持plugin机制(比如存在一些早期的组件,利用反射形成相互的依赖关系,但OSGI是不支持相互依赖的)。
这个时候怎么办呢?
因为我们track了半天Log4j的代码,也没有找到如何判断“当前的Log4j已经配置过了,不需要再配置了”。否则,就会很容易造成配置冲突。有可能存在同一个classloader中,有些组件都采用了log4j的Congfigurator来进行“透明化”配置,但是这些透明化配置因为无法判断log4j是否已经初始化,而造成重复配置、覆盖配置的问题。
目前这个问题的解决方案还在和美国那边协商,解决方案尚未最后定。
是因为我们为客户考虑的太多,而把Log4j问题想复杂了;还是因为以前陈旧的代码阻碍了我们;抑或是OSGI的机制还有待改善。总之,这一次,Log4j被OSGI撞了一下腰,我们是被撞了一下腰。

相关文章:

  • 比较分析Vector、ArrayList和hashtable hashmap数据结构
  • java二进制类型_Java数据类型 - 原始和二进制文字
  • hibernate的Criteria的一个bug
  • toad导出mysql数据库_将toad里的数据库结构导出到pdm
  • 炒股精髓:多位高手多年心血结晶
  • 好神奇哟
  • java linux 压缩文件夹_Linux下压缩某个文件夹(文件夹打包)
  • java中mapper层作用_Java的MyBatis框架中Mapper映射配置的使用及原理解析
  • java空接口_java中RandomAccess接口明明是个空接口,有什么用呢?
  • java pdf base64_Javaweb中利用pdf.js显示oracle数据库中Base64编码转为的PDF
  • SQL Server 2005豪华盛宴
  • java班级管理系统代码_基于jsp的班级管理系统-JavaEE实现班级管理系统 - java项目源码...
  • java 聚合服务_远程服务接口聚合带来的性能提升
  • java编写客户_java编写服务器和客户端.docx
  • ORA-03113错误分析
  • 【刷算法】求1+2+3+...+n
  • es6要点
  • FineReport中如何实现自动滚屏效果
  • Linux各目录及每个目录的详细介绍
  • Python3爬取英雄联盟英雄皮肤大图
  • Spring Cloud中负载均衡器概览
  • VUE es6技巧写法(持续更新中~~~)
  • 第2章 网络文档
  • 第十八天-企业应用架构模式-基本模式
  • 基于Android乐音识别(2)
  • 理解 C# 泛型接口中的协变与逆变(抗变)
  • 浅谈Golang中select的用法
  • 深入浏览器事件循环的本质
  • 数据可视化之 Sankey 桑基图的实现
  • 再次简单明了总结flex布局,一看就懂...
  • zabbix3.2监控linux磁盘IO
  • 阿里云API、SDK和CLI应用实践方案
  • ### Error querying database. Cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException
  • #、%和$符号在OGNL表达式中经常出现
  • #ubuntu# #git# repository git config --global --add safe.directory
  • (4) openssl rsa/pkey(查看私钥、从私钥中提取公钥、查看公钥)
  • (JS基础)String 类型
  • (pt可视化)利用torch的make_grid进行张量可视化
  • (Pytorch框架)神经网络输出维度调试,做出我们自己的网络来!!(详细教程~)
  • (备忘)Java Map 遍历
  • (附源码)springboot金融新闻信息服务系统 毕业设计651450
  • (附源码)计算机毕业设计SSM智慧停车系统
  • (接口自动化)Python3操作MySQL数据库
  • (十二)springboot实战——SSE服务推送事件案例实现
  • (数位dp) 算法竞赛入门到进阶 书本题集
  • (转)fock函数详解
  • (转)shell调试方法
  • .helper勒索病毒的最新威胁:如何恢复您的数据?
  • .NET中统一的存储过程调用方法(收藏)
  • .secret勒索病毒数据恢复|金蝶、用友、管家婆、OA、速达、ERP等软件数据库恢复
  • @Controller和@RestController的区别?
  • @RequestMapping 的作用是什么?
  • @Resource和@Autowired的区别
  • @开发者,一文搞懂什么是 C# 计时器!
  • [<死锁专题>]