Learning logging framework 2

1.slf4j source code analysis

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private Logger log = LoggerFactory.getLogger(this.getClass());

1.1 getLogger analytical method

 public static Logger getLogger(Class<?> clazz) {
        Logger logger = getLogger(clazz.getName());
        if (DETECT_LOGGER_NAME_MISMATCH) {
            Class<?> autoComputedCallingClass = Util.getCallingClass();
            if (autoComputedCallingClass != null && nonMatchingClasses(clazz, autoComputedCallingClass)) {
                Util.report(String.format("Detected logger name mismatch. Given name: \"%s\"; computed name: \"%s\".", logger.getName(),
                                autoComputedCallingClass.getName()));
                Util.report("See " + LOGGER_NAME_MISMATCH_URL + " for an explanation");
            }
        }
        return logger;
    }

After half of the logic: When passed in class and the caller's name clazz whether to print a warning inconsistent information (default is not printed),

1.2getLogger specific implementation method:

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

Acquiring a corresponding class factory implementation by getILoggerFactory, then acquires the corresponding log object

Detailed methods 1.3getILoggerFactory

public static ILoggerFactory getILoggerFactory() {
        if (INITIALIZATION_STATE == UNINITIALIZED) {
            synchronized (LoggerFactory.class) {
                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://jira.qos.ch/browse/SLF4J-97
            return SUBST_FACTORY;
        }
        throw new IllegalStateException("Unreachable code");
    }

First execution performInitialization initialized into operation according to different values ​​of INITIALIZATION_STATE (initialized successfully used to return a factory class, which in turn acquires a corresponding log object)

1.4performInitialization Method Description

 private final static void performInitialization() {
        bind();
        if (INITIALIZATION_STATE == SUCCESSFUL_INITIALIZATION) {
            versionSanityCheck();
        }
    }

Methods bind to the actual performInitialization, versionSanityCheck just took jdk version checking, not described in detail again
1.5bind

private final static void bind() {
        try {
            Set<URL> staticLoggerBinderPathSet = null;
            // skip check under android, see also
            // http://jira.qos.ch/browse/SLF4J-328
            if (!isAndroid()) {
                staticLoggerBinderPathSet = findPossibleStaticLoggerBinderPathSet();
                reportMultipleBindingAmbiguity(staticLoggerBinderPathSet);
            }
            // the next line does the binding
            StaticLoggerBinder.getSingleton();
            INITIALIZATION_STATE = SUCCESSFUL_INITIALIZATION;
            reportActualBinding(staticLoggerBinderPathSet);
            fixSubstituteLoggers();
            replayEvents();
            // release all resources in SUBST_FACTORY
            SUBST_FACTORY.clear();
        } 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.contains("org.slf4j.impl.StaticLoggerBinder.getSingleton()")) {
                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);
        }
    }

bind key method
findPossibleStaticLoggerBinderPathSet (); - Looking for binding path
StaticLoggerBinder.getSingleton (); - obtaining binding factory method
fixSubstituteLoggers (); - did not understand what the role is, there is hope to see the next big brother pointing
replayEvents (); - did not understand what the role is, there are big brothers to see under the guidance of hope

1.5.1findPossibleStaticLoggerBinderPathSet

static Set<URL> findPossibleStaticLoggerBinderPathSet() {
        // use Set instead of list in order to deal with bug #138
        // LinkedHashSet appropriate here because it preserves insertion order
        // during iteration
        Set<URL> staticLoggerBinderPathSet = new LinkedHashSet<URL>();
        try {
            ClassLoader loggerFactoryClassLoader = LoggerFactory.class.getClassLoader();
            Enumeration<URL> paths;
            if (loggerFactoryClassLoader == null) {
                paths = ClassLoader.getSystemResources(STATIC_LOGGER_BINDER_PATH);
            } else {
                paths = loggerFactoryClassLoader.getResources(STATIC_LOGGER_BINDER_PATH);
            }
            while (paths.hasMoreElements()) {
                URL path = paths.nextElement();
                staticLoggerBinderPathSet.add(path);
            }
        } catch (IOException ioe) {
            Util.report("Error getting resources from path", ioe);
        }
        return staticLoggerBinderPathSet;
    }

Get all org / slf4j / impl class path StaticLoggerBinder.class / (a warning when the acquisition is larger than but only warnings do not affect the operation)
See the official documentation:

The warning emitted by SLF4J is just that, a warning. Even when multiple bindings are present, SLF4J will pick one logging
framework/implementation and bind with it. The way SLF4J picks a
binding is determined by the JVM and for all practical purposes should
be considered random. As of version 1.6.6, SLF4J will name the
framework/implementation class it is actually bound to.
Embedded components such as libraries or frameworks should not declare a dependency on any SLF4J binding but only depend on
slf4j-api. When a library declares a compile-time dependency on a
SLF4J binding, it imposes that binding on the end-user, thus negating
SLF4J’s purpose. When you come across an embedded component declaring
a compile-time dependency on any SLF4J binding, please take the time
to contact the authors of said component/library and kindly ask them
to mend their ways.

1.5.2 (slf4j key)
StaticLoggerBinder class using a class that is found in all paths findPossibleStaticLoggerBinderPathSet (particularly jvm loaded classes according to the order, the order according to Experiment I obtained is the reference sequence jar, for example, while introducing slf4j-nop. jar slf4j-simple.jar, slf4j-log4j12.jar , slf4j-jdk14.jar, logback-classic.jar, uses slf4j-nop.jar in StaticLoggerBinder to obtain a corresponding class factory)
As slf4j-api. StaticLoggerBinder source code in fact, the class played a jar slf4j-api.jar is non-existent because of his pom file written, when packaging will remove the source code directory and its impl next file.

1.5.3 reportActualBinding
output StaticLoggerBinder actual (binding) used

Published 21 original articles · won praise 6 · views 30000 +

Guess you like

Origin blog.csdn.net/soulonlyhlh/article/details/85841194