LogFacade---SLF4J

概述

Simple Logging Facade for Java(SLF4J);

用作各种日志框架(eg:java.util.logging,logback,log4j)的简单外观或抽象,允许最终用户在部署 时插入所需的日志记录框架;

 

不提供完整的日志记录解决方案;

使用SLF4J无法执行配置appender或设置日志记录级别等操作。

因此,在某个时间点,任何非平凡的应用程序都需要直接调用底层日志记录系统;

因此一般情况下slf4j都会和log4j,logback等日志框架一起使用;

 

slf4j是一个日志标准,同时日志框架都会实现这个标准,因此使用slf4j可以极大的降低维护成本;

 

SPI机制

  

   slf4j 提供的 service LoggerFactory ,在Classpath下查找 org/slf4j/impl/StaticLoggerBinder.class

 

链路

LoggerFactory.getLogger

// org.slf4j.LoggerFactory.getLogger(java.lang.Class)
    // Return a logger named corresponding to the class passed as parameter, using the statically bound {@link ILoggerFactory} instance.
    public static Logger getLogger(Class clazz) {
        return getLogger(clazz.getName());
    }

    // org.slf4j.LoggerFactory.getLogger(java.lang.String)
    // Return a logger named according to the name parameter using the statically bound {@link ILoggerFactory} instance.
    public static Logger getLogger(String name) {
        ILoggerFactory iLoggerFactory = getILoggerFactory();
        return iLoggerFactory.getLogger(name);
    }

    // org.slf4j.LoggerFactory.getILoggerFactory
    // Return the {@link ILoggerFactory} instance in use.ILoggerFactory instance is bound with this class at compile time.
    public static ILoggerFactory getILoggerFactory() {
        if (INITIALIZATION_STATE == UNINITIALIZED) {
            INITIALIZATION_STATE = ONGOING_INITIALIZATION;
            performInitialization();
        }
        switch (INITIALIZATION_STATE) {
            case SUCCESSFUL_INITIALIZATION:
                return StaticLoggerBinder.getSingleton().getLoggerFactory();
            case NOP_FALLBACK_INITIALIZATION:
                return NOP_FALLBACK_FACTORY;
            case FAILED_INITIALIZATION:
                throw new IllegalStateException(UNSUCCESSFUL_INIT_MSG);
            case ONGOING_INITIALIZATION:
                // support re-entrant behavior.
                // See also http://bugzilla.slf4j.org/show_bug.cgi?id=106
                return TEMP_FACTORY;
        }
        throw new IllegalStateException("Unreachable code");
    }

    // org.slf4j.LoggerFactory.performInitialization
    private final static void performInitialization() {
        bind();
        if (INITIALIZATION_STATE == SUCCESSFUL_INITIALIZATION) {
            versionSanityCheck();
        }
    }

    // org.slf4j.LoggerFactory.bind
    private final static void bind() {
        try {
            Set staticLoggerBinderPathSet = findPossibleStaticLoggerBinderPathSet();  // 获取classpath下的org/slf4j/impl/StaticLoggerBinder.class
            reportMultipleBindingAmbiguity(staticLoggerBinderPathSet);
            // the next line does the binding
            StaticLoggerBinder.getSingleton();                                         //
            INITIALIZATION_STATE = SUCCESSFUL_INITIALIZATION;
            reportActualBinding(staticLoggerBinderPathSet);
            emitSubstituteLoggerWarning();
        } catch (NoClassDefFoundError ncde) {
            String msg = ncde.getMessage();
            if (messageContainsOrgSlf4jImplStaticLoggerBinder(msg)) {
                INITIALIZATION_STATE = NOP_FALLBACK_INITIALIZATION;
                Util.report("Failed to load class \"org.slf4j.impl.StaticLoggerBinder\".");
                Util.report("Defaulting to no-operation (NOP) logger implementation");
                Util.report("See " + NO_STATICLOGGERBINDER_URL
                        + " for further details.");
            } else {
                failedBinding(ncde);
                throw ncde;
            }
        } catch (java.lang.NoSuchMethodError nsme) {
            String msg = nsme.getMessage();
            if (msg != null && msg.indexOf("org.slf4j.impl.StaticLoggerBinder.getSingleton()") != -1) {
                INITIALIZATION_STATE = FAILED_INITIALIZATION;
                Util.report("slf4j-api 1.6.x (or later) is incompatible with this binding.");
                Util.report("Your binding is version 1.5.5 or earlier.");
                Util.report("Upgrade your binding to version 1.6.x.");
            }
            throw nsme;
        } catch (Exception e) {
            failedBinding(e);
            throw new IllegalStateException("Unexpected initialization failure", e);
        }
    }

    // org.slf4j.LoggerFactory.findPossibleStaticLoggerBinderPathSet
    // We need to use the name of the StaticLoggerBinder class, but we can't reference the class itself.
    private static Set findPossibleStaticLoggerBinderPathSet() {
        // use Set instead of list in order to deal with  bug #138
        // LinkedHashSet appropriate here because it preserves insertion order during iteration
        Set staticLoggerBinderPathSet = new LinkedHashSet();
        try {
            ClassLoader loggerFactoryClassLoader = LoggerFactory.class.getClassLoader();
            Enumeration paths;
            if (loggerFactoryClassLoader == null) {
                paths = ClassLoader.getSystemResources(STATIC_LOGGER_BINDER_PATH);
            } else {
                paths = loggerFactoryClassLoader.getResources(STATIC_LOGGER_BINDER_PATH);   // 获取classpath下的org/slf4j/impl/StaticLoggerBinder.class
            }
            while (paths.hasMoreElements()) {
                URL path = (URL) paths.nextElement();
                staticLoggerBinderPathSet.add(path);
            }
        } catch (IOException ioe) {
            Util.report("Error getting resources from path", ioe);
        }
        return staticLoggerBinderPathSet;
    }

    // org.slf4j.impl.StaticLoggerBinder.getSingleton
    public static StaticLoggerBinder getSingleton() {
        return SINGLETON;
    }

    // ch.qos.logback.classic.LoggerContext.getLogger(java.lang.String)
    public final Logger getLogger(final String name) {
        //...
        Logger childLogger = (Logger) loggerCache.get(name);       // 从缓存中取对应name的Logger  
        //...
        loggerCache.put(childName, childLogger);
    }

  

log.debug

由具体的 log 实现;

 

posted on 2023-11-29 18:26  anpeiyong  阅读(16)  评论(0编辑  收藏  举报

导航