我们在使用logback一类的logging system的时候
总是在代码的前面部分放上这段代码private final Logger log = LoggerFactory.getLogger(AdController.class
这段代码调用了org.slf4j.LoggerFactory line:280
- public static Logger getLogger(Class clazz) {
- return getLogger(clazz.getName());
- }
- public static Logger getLogger(String name) {
- ILoggerFactory iLoggerFactory = getILoggerFactory();
- return iLoggerFactory.getLogger(name);
- }
进入 ch.qos.logback.classic.LoggerContext line:105
Logger childLogger = (Logger) loggerCache.get(name);
loggerCache定义处private Map<String, Logger> loggerCache;
初始化代码
- public LoggerContext() {
- super();
- this.loggerCache = new ConcurrentHashMap<String, Logger>();
- this.loggerContextRemoteView = new LoggerContextVO(this);
- this.root = new Logger(Logger.ROOT_LOGGER_NAME, null, this);
- this.root.setLevel(Level.DEBUG);
- loggerCache.put(Logger.ROOT_LOGGER_NAME, root);
- initEvaluatorMap();
- size = 1;
- this.frameworkPackages = new ArrayList<String>();
- }
可以看到logger里通过name获取logger的实际上是访问了loggerCache这个支持高并发的hashmap.
以下50行代码 做了最重要的工作,请大家仔细阅读,就会明白了.其实很简单.
- public final Logger getLogger(final String name) {
- if (name == null) {
- throw new IllegalArgumentException("name argument cannot be null");
- }
- // if we are asking for the root logger, then let us return it without
- // wasting time
- if (Logger.ROOT_LOGGER_NAME.equalsIgnoreCase(name)) {
- return root;
- }
- int i = 0;
- Logger logger = root;
- // check if the desired logger exists, if it does, return it
- // without further ado.
- Logger childLogger = (Logger) loggerCache.get(name);
- // if we have the child, then let us return it without wasting time
- if (childLogger != null) {
- return childLogger;
- }
- // if the desired logger does not exist, them create all the loggers
- // in between as well (if they don't already exist)
- String childName;
- while (true) {
- int h = LoggerNameUtil.getSeparatorIndexOf(name, i);
- if (h == -1) {
- childName = name;
- } else {
- childName = name.substring(0, h);
- }
- // move i left of the last point
- i = h + 1;
- synchronized (logger) {
- childLogger = logger.getChildByName(childName);
- if (childLogger == null) {
- childLogger = logger.createChildByName(childName);
- loggerCache.put(childName, childLogger);
- incSize();
- }
- }
- logger = childLogger;
- if (h == -1) {
- return childLogger;
- }
- }
- }
比如 我们给的name是com.colamachine.calendar.CalendarService
那么他会第一次会去找com 如果没有com就创建com的logger
再去寻找com.colamachine 同上创建
再去找并创建com.colamachine.calendar
再去找并创建com.colamachine.calendar.CalendarService.
好看完了代码,这只是我一厢情愿的猜测.现在来开始
果然如此
这样的机制 在内存的开销上是否过大
对于只有6个模块的小系统,轻轻松松的mapsize达到了532个