当我们在用LoggerFactory.getLogger(xyz.class)时我们在干什么

我们在使用logback一类的logging system的时候

总是在代码的前面部分放上这段代码private final Logger log = LoggerFactory.getLogger(AdController.class


这段代码调用了org.slf4j.LoggerFactory line:280

  1. public static Logger getLogger(Class clazz) {
  2. return getLogger(clazz.getName());
  3. }

  1. public static Logger getLogger(String name) {
  2. ILoggerFactory iLoggerFactory = getILoggerFactory();
  3. return iLoggerFactory.getLogger(name);
  4. }

进入 ch.qos.logback.classic.LoggerContext  line:105

 

   Logger childLogger = (Logger) loggerCache.get(name);
loggerCache定义处

private Map<String, Logger> loggerCache;

初始化代码

  1. public LoggerContext() {
  2. super();
  3. this.loggerCache = new ConcurrentHashMap <String, Logger>();
  4. this.loggerContextRemoteView = new LoggerContextVO(this);
  5. this.root = new Logger(Logger.ROOT_LOGGER_NAME, null, this);
  6. this.root.setLevel(Level.DEBUG);
  7. loggerCache.put(Logger.ROOT_LOGGER_NAME, root);
  8. initEvaluatorMap();
  9. size = 1;
  10. this.frameworkPackages = new ArrayList <String>();
  11. }

可以看到logger里通过name获取logger的实际上是访问了loggerCache这个支持高并发的hashmap.

以下50行代码 做了最重要的工作,请大家仔细阅读,就会明白了.其实很简单.

  1. public final Logger getLogger(final String name) {
  2. if (name == null) {
  3. throw new IllegalArgumentException("name argument cannot be null");
  4. }
  5. // if we are asking for the root logger, then let us return it without
  6. // wasting time
  7. if (Logger.ROOT_LOGGER_NAME.equalsIgnoreCase(name)) {
  8. return root;
  9. }
  10. int i = 0;
  11. Logger logger = root;
  12. // check if the desired logger exists, if it does, return it
  13. // without further ado.
  14. Logger childLogger = (Logger) loggerCache.get(name);
  15. // if we have the child, then let us return it without wasting time
  16. if (childLogger != null) {
  17. return childLogger;
  18. }
  19. // if the desired logger does not exist, them create all the loggers
  20. // in between as well (if they don't already exist)
  21. String childName;
  22. while (true) {
  23. int h = LoggerNameUtil.getSeparatorIndexOf(name, i);
  24. if (h == -1) {
  25. childName = name;
  26. } else {
  27. childName = name.substring(0, h);
  28. }
  29. // move i left of the last point
  30. i = h + 1;
  31. synchronized (logger) {
  32. childLogger = logger.getChildByName(childName);
  33. if (childLogger == null) {
  34. childLogger = logger.createChildByName(childName);
  35. loggerCache.put(childName, childLogger);
  36. incSize();
  37. }
  38. }
  39. logger = childLogger;
  40. if (h == -1) {
  41. return childLogger;
  42. }
  43. }
  44. }
如果获取不了,就进入一个循环遍历

比如 我们给的name是com.colamachine.calendar.CalendarService

那么他会第一次会去找com 如果没有com就创建com的logger

再去寻找com.colamachine 同上创建

再去找并创建com.colamachine.calendar

再去找并创建com.colamachine.calendar.CalendarService.

好看完了代码,这只是我一厢情愿的猜测.现在来开始

果然如此 

这样的机制 在内存的开销上是否过大

对于只有6个模块的小系统,轻轻松松的mapsize达到了532个

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值