log4j2婧愮爜鍒嗘瀽-1

Posted 涓€鍙皬绗ㄩ緹

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了log4j2婧愮爜鍒嗘瀽-1相关的知识,希望对你有一定的参考价值。


涓€鍙皬绗ㄩ緹馃悽锛屽叕浼楀彿锛氫竴鍙皬绗ㄩ緹
鎺?/span>涓?/span>涓€绡?/span>鏂囩珷锛?/span>鏈瘒鏂囩珷寮€濮嬶紝浼氬log4j2鐨勬簮鐮佽繘琛屽垎鏋愶紝鏈枃绔犱富瑕佷粙缁峫og4j2涓殑涓€浜涢噸瑕佹蹇典互鍙婅幏鍙栨墽琛?/span> logger鐨勮繃绋嬨€?/span>

1. 閲嶈姒傚康

LogManager

log绠$悊鍣紝鎻愪緵闈欐€佹柟娉昰etContext锛実etFactory锛実etLogger锛屽彲浠ユ柟渚跨殑鑾峰彇鐩稿叧淇℃伅銆?/span>

LoggerContext

The LoggerContext is the anchor for the logging system銆傜畝鍗曟潵璇达紝灏辨槸鏃ュ織涓婁笅鏂囷紝鍖呭惈宸查厤缃殑Configuration銆丄ppender锛孡ogger锛孎ilter绛変俊鎭€?/p>

LoggerContextFactory

loggerContext宸ュ巶锛屽湪log4j涓叿浣撴槸Log4jContextFactory锛岄€変腑ContextSelector骞朵笖鍔犺浇鐩稿簲鐨凩oggerContext銆傛彁渚沢etContext()鏂规硶鑾峰彇loggerContext锛屾彁渚況emoveContext()鏂规硶绉婚櫎loggerContext銆?/span>

ContextSelector

杩斿洖涓€涓狶oggerContext銆?/span>

Configuration

 姣忎竴涓狶oggerContext閮芥湁涓€涓湁鏁堢殑Configuration銆侰onfiguration鍖呭惈浜嗘墍鏈夌殑Appenders銆佷笂涓嬫枃鑼冨洿鍐呯殑杩囨护鍣ㄣ€丩oggerConfigs浠ュ強StrSubstitutor.鐨勫紩鐢ㄣ€傚湪閲嶉厤缃湡闂达紝鏂颁笌鏃х殑Configuration灏嗗悓鏃跺瓨鍦ㄣ€傚綋鎵€鏈夌殑Logger瀵硅薄閮借閲嶅畾鍚戝埌鏂扮殑Configuration瀵硅薄鍚庯紝鏃х殑Configuration瀵硅薄灏嗚鍋滅敤鍜屼涪寮冦€?/p>

 Logger

Loggers 鏄€氳繃璋冪敤LogManager.getLogger鏂规硶鑾峰緱鐨勩€侺ogger瀵硅薄鏈韩骞朵笉瀹炶浠讳綍瀹為檯鐨勫姩浣溿€傚畠鍙槸鎷ユ湁涓€涓猲ame 浠ュ強涓庝竴涓狶oggerConfig鐩稿叧鑱斻€傚畠缁ф壙浜咥bstractLogger绫诲苟瀹炵幇浜嗘墍闇€鐨勬柟娉曘€傚綋Configuration鏀瑰彉鏃讹紝Logger灏嗕細涓庡彟澶栫殑LoggerConfig鐩稿叧鑱旓紝浠庤€屾敼鍙樿繖涓狶ogger鐨勮涓恒€?/p>

LoggerConfig

姣忎釜LoggerConfig鍜宭ogger鏄搴旂殑锛岃幏鍙栧埌涓€涓猯ogger锛屽啓鏃ュ織鏃跺叾瀹炴槸閫氳繃LoggerConfig鏉ヨ鏃ュ織鐨勩€?/p>

2.鎵ц杩囩▼鍒嗘瀽

LoggerFactory.getLogger() 鏂规硶

//璋冪敤LoggerFactory.getLogger鏂规硶public L getLogger(final String name) { //鑾峰彇Context final LoggerContext context = getContext(); final ConcurrentMap<String, L> loggers = getLoggersInContext(context); final L logger = loggers.get(name); if (logger != null) { return logger; } loggers.putIfAbsent(name, newLogger(name, context)); return loggers.get(name); }

LogManager.getContext鏂规硶

factory鏄疞oggerContextFactory锛屽彲浠ョ悊瑙f垚鏄疌ontext鐨勭敓浜у伐鍘傦紝鍦↙oggerContext闈欐€佷唬鐮佸潡涓垵濮嬪寲銆傜户缁繘鍏actory.getContext(FQCN, null, null, true)鏂规硶涓紝杩涘叆瀹炵幇绫籐og4jContextFactory涓€?/p>

public static LoggerContext getContext() { try { //LoggerContextFactory factory; return factory.getContext(FQCN, null, null, true); } catch (final IllegalStateException ex) { LOGGER.warn(ex.getMessage() + " Using SimpleLogger"); return new SimpleLoggerContextFactory().getContext(FQCN, null, null, true); } }

LoggerContext鏄粠selector.getContext(fqcn, loader, currentContext)涓幏鍙栫殑锛屾鏃跺垽鏂璫tx.getState()鏄惁绛変簬LifeCycle.State.INITIALIZED锛岀涓€娆¤皟鐢╣etlogger()鏃讹紝浼氭墽琛宑tx.start()鏂规硶銆?/p>

public LoggerContext getContext(final String fqcn, final ClassLoader loader, final Object externalContext, final boolean currentContext) { //selector鏄竴涓狢ontext閫夋嫨鍣紝閫夋嫨婊¤冻褰撳墠椤圭洰瑕佹眰鐨凜ontext final LoggerContext ctx = selector.getContext(fqcn, loader, currentContext); if (externalContext != null && ctx.getExternalContext() == null) { ctx.setExternalContext(externalContext); } //棣栨璇锋眰鏃讹紝浼氭墽琛宑tx.start鏂规硶杩涜context鐨勫垵濮嬪寲銆?/span> if (ctx.getState() == LifeCycle.State.INITIALIZED) { ctx.start(); } return ctx; }

ctx.start()鏂规硶

public void start() { LOGGER.debug("Starting LoggerContext[name={}, {}]...", getName(), this); if (PropertiesUtil.getProperties().getBooleanProperty("log4j.LoggerContext.stacktrace.on.start", false)) { LOGGER.debug("Stack trace to locate invoker", new Exception("Not a real error, showing stack trace to locate invoker")); } if (configLock.tryLock()) { try { //濡傛灉鏄垵濮嬪寲璇锋眰锛屼細鎵цreconfigure()鏂规硶锛岃鏂规硶鍗充负灏嗛厤缃枃浠秎og4j2.xml瑙f瀽鎴怌onfiguration閰嶇疆銆?/span> if (this.isInitialized() || this.isStopped()) { this.setStarting(); reconfigure(); if (this.configuration.isShutdownHookEnabled()) { setUpShutdownHook(); } this.setStarted(); } } finally { configLock.unlock(); } } LOGGER.debug("LoggerContext[name={}, {}] started OK.", getName(), this); }

reconfigure()鏂规硶

閰嶇疆鏂囦欢log4j2.xml灏辨槸璇ュ嚱鏁颁腑瀹炵幇鐨勶紝ConfigurationFactory.getInstance().getConfiguration(this, contextName, configURI, cl)寰楀埌浜嗛厤缃枃浠讹紝骞惰В鏋愭垚Configuration銆傝繘鍏etConfiguration(instance)鏂规硶锛屽惎鍔ㄥ綋鍓嶇殑configuration锛屽苟瑙f瀽璇ラ厤缃笅鐨勬墍鏈塧ppender锛宭ogger鍜宺oot銆?/span>
private void reconfigure(final URI configURI) { final ClassLoader cl = ClassLoader.class.isInstance(externalContext) ? (ClassLoader) externalContext : null; LOGGER.debug("Reconfiguration started for context[name={}] at URI {} ({}) with optional ClassLoader: {}", contextName, configURI, this, cl); final Configuration instance = ConfigurationFactory.getInstance().getConfiguration(this, contextName, configURI, cl); if (instance == null) { LOGGER.error("Reconfiguration failed: No configuration found for '{}' at '{}' in '{}'", contextName, configURI, cl); } else { setConfiguration(instance); /* * instance.start(); Configuration old = setConfiguration(instance); updateLoggers(); if (old != null) { * old.stop(); } */ final String location = configuration == null ? "?" : String.valueOf(configuration.getConfigurationSource()); LOGGER.debug("Reconfiguration complete for context[name={}] at URI {} ({}) with optional ClassLoader: {}", contextName, location, this, cl); } }
public Configuration setConfiguration(final Configuration config) { if (config == null) { LOGGER.error("No configuration found for context '{}'.", contextName); // No change, return the current configuration. return this.configuration; } configLock.lock(); try { final Configuration prev = this.configuration; config.addListener(this); final ConcurrentMap<String, String> map = config.getComponent(Configuration.CONTEXT_PROPERTIES); try { // LOG4J2-719 network access may throw android.os.NetworkOnMainThreadException map.putIfAbsent("hostName", NetUtils.getLocalHostname()); } catch (final Exception ex) { LOGGER.debug("Ignoring {}, setting hostName to 'unknown'", ex.toString()); map.putIfAbsent("hostName", "unknown"); } map.putIfAbsent("contextName", contextName); config.start(); this.configuration = config; updateLoggers(); if (prev != null) { prev.removeListener(this); prev.stop(); } firePropertyChangeEvent(new PropertyChangeEvent(this, PROPERTY_CONFIG, prev, config)); try { Server.reregisterMBeansAfterReconfigure(); } catch (final LinkageError | Exception e) { // LOG4J2-716: Android has no java.lang.management LOGGER.error("Could not reconfigure JMX", e); } // AsyncLoggers update their nanoClock when the configuration changes Log4jLogEvent.setNanoClock(configuration.getNanoClock());
return prev; } finally { configLock.unlock(); } }

LoggerFactory.getLogger()鏂规硶

鎴鐩墠锛孡oggerContext宸茬粡鎴愬姛鍒濆鍖栵紝涓嬮潰灏辨槸浠嶭oggerContext涓幏鍙栧叿浣撶殑Logger銆?/p>

濡傛灉鏈粠context涓幏鍙栧埌鍚嶇О涓簄ame鐨刲ogger锛屽垯浼氭墽琛宯ewLogger鏂规硶锛屾柊寤轰竴涓狶ogger銆?/p>

public L getLogger(final String name) { final LoggerContext context = getContext(); final ConcurrentMap<String, L> loggers = getLoggersInContext(context); final L logger = loggers.get(name); if (logger != null) { return logger; } loggers.putIfAbsent(name, newLogger(name, context)); return loggers.get(name); }

getLoggersInContext()鏂规硶

璇ユ柟娉曢€氳繃浼犲叆鐨刢ontext锛屼粠registry涓幏鍙杔oggers銆?/p>

//浠ontext涓簁ey锛孋oncurrentMap<loggerName,Logger>涓簐alue鐨刴approtected final Map<LoggerContext, ConcurrentMap<String, L>> registry = new ConcurrentHashMap<>();
public ConcurrentMap<String, L> getLoggersInContext(final LoggerContext context) { ConcurrentMap<String, L> loggers; lock.readLock ().lock (); try { loggers = registry.get (context); } finally { lock.readLock ().unlock (); }
if (loggers != null) { return loggers; } //濡傛灉context瀵逛簬鐨刲ogger瀹瑰櫒杩樹笉瀛樺湪锛屾柊寤?/span> lock.writeLock ().lock (); try { loggers = registry.get (context); if (loggers == null) { loggers = new ConcurrentHashMap<> (); registry.put (context, loggers); if (context instanceof LoggerContextShutdownEnabled) { ((LoggerContextShutdownEnabled) context).addShutdownListener(this); } } return loggers; } finally { lock.writeLock ().unlock (); } }

newLogger()鏂规硶

鏂板缓涓€涓狶og4jLogger瀵硅薄銆?/p>

protected Logger newLogger(final String name, final LoggerContext context) { final String key = Logger.ROOT_LOGGER_NAME.equals(name) ? LogManager.ROOT_LOGGER_NAME : name; return new Log4jLogger(validateContext(context).getLogger(key), name); }
@Override public Logger getLogger(final String name) { return getLogger(name, null); }
//@Overridepublic Logger getLogger(final String name, final MessageFactory messageFactory) { // Note: This is the only method where we add entries to the 'loggerRegistry' ivar. Logger logger = loggerRegistry.getLogger(name, messageFactory); if (logger != null) { AbstractLogger.checkMessageFactory(logger, messageFactory); return logger; } //閫氳繃浠ヤ笂鏈壘鍒癓ogger锛屾墽琛宯ewInstance鏂规硶锛屽垱寤簂ogger logger = newInstance(this, name, messageFactory); loggerRegistry.putIfAbsent(name, messageFactory, logger); return loggerRegistry.getLogger(name, messageFactory); }

newInstance()鏂规硶

protected Logger newInstance(final LoggerContext ctx, final String name, final MessageFactory messageFactory) { return new Logger(ctx, name, messageFactory); }

protected Logger(final LoggerContext context, final String name, final MessageFactory messageFactory) { super(name, messageFactory); this.context = context; privateConfig = new PrivateConfig(context.getConfiguration(), this); }
//logger閰嶇疆淇℃伅public PrivateConfig(final Configuration config, final Logger logger) { this.config = config; this.loggerConfig = config.getLoggerConfig(getName()); this.loggerConfigLevel = this.loggerConfig.getLevel(); this.intLevel = this.loggerConfigLevel.intLevel(); this.logger = logger; this.requiresLocation = this.loggerConfig.requiresLocation(); }
//鍙互鐪嬪埌棣栧厛浠巐oggerConfigs涔熷氨鏄厤缃枃浠朵腑閰嶇疆鐨刲ogger涓幏鍙栵紝濡傛灉鑾峰彇涓嶅埌鍒欏惊鐜€掑綊name涓?."涔嬪墠鐨刲ogger锛屽鏋滆繕鏄幏鍙栦笉鍒帮紝鍒欓粯璁や娇鐢╮oot鐨勯厤缃€?/span>public LoggerConfig getLoggerConfig(final String loggerName) { LoggerConfig loggerConfig = loggerConfigs.get(loggerName); if (loggerConfig != null) { return loggerConfig; } String substr = loggerName; while ((substr = NameUtil.getSubName(substr)) != null) { loggerConfig = loggerConfigs.get(substr); if (loggerConfig != null) { return loggerConfig; } } return root; }

浠ヤ笂鍒嗘瀽鎴愬姛鐨勬嬁鍒颁簡闇€瑕佺殑logger锛屼笅闈㈠紑濮嬪垎鏋愬叿浣撶殑logger鏂规硶銆?/span>

logger.info("===this is test log info===");

logger.info()鏂规硶

public void info(final String format) { logger.logIfEnabled(FQCN, Level.INFO, null, format); }
public void logIfEnabled(final String fqcn, final Level level, final Marker marker, final String message) { //濡傛灉婊¤冻鎵撳嵃鏉′欢锛屽垯杩涜鎵撳嵃銆?/span> if (isEnabled(level, marker, message)) { logMessage(fqcn, level, marker, message); } }//鏍规嵁config閰嶇疆涓殑level涓€绾ilter鍒ゆ柇鏄惁鍙互鎵撳嵃鏃ュ織銆?/span> public boolean isEnabled(final Level level, final Marker marker, final String message) { return privateConfig.filter(level, marker, message); }
boolean filter(final Level level, final Marker marker, final String msg) { final Filter filter = config.getFilter(); //杩囨护鍣ㄦ牎楠? if (filter != null) { final Filter.Result r = filter.filter(logger, level, marker, msg); if (r != Filter.Result.NEUTRAL) { return r == Filter.Result.ACCEPT; } } //鏃ュ織绾у埆鏍¢獙 return level != null && intLevel >= level.intLevel(); }

logMessage()鏂规硶

protected void logMessage(final String fqcn, final Level level, final Marker marker, final String message) { //鏋勯€燤essage瀵硅薄 final Message msg = messageFactory.newMessage(message); logMessageSafely(fqcn, level, marker, msg, msg.getThrowable()); }
private void logMessageSafely(final String fqcn, final Level level, final Marker marker, final Message msg, final Throwable throwable) { try { logMessageTrackRecursion(fqcn, level, marker, msg, throwable); } finally { // LOG4J2-1583 prevent scrambled logs when logging calls are nested (logging in toString()) ReusableMessageFactory.release(msg); } }
private void logMessageTrackRecursion(final String fqcn, final Level level, final Marker marker, final Message msg, final Throwable throwable) { try { incrementRecursionDepth(); // LOG4J2-1518, LOG4J2-2031 tryLogMessage(fqcn, level, marker, msg, throwable); } finally { decrementRecursionDepth(); } }
private void tryLogMessage(final String fqcn, final Level level, final Marker marker, final Message msg, final Throwable throwable) { try { log(level, marker, fqcn, location, msg, throwable); } catch (final Exception e) { // LOG4J2-1990 Log4j2 suppresses all exceptions that occur once application called the logger handleLogMessageException(e, fqcn, msg); } }
protected void log(final Level level, final Marker marker, final String fqcn, final StackTraceElement location, final Message message, final Throwable throwable) { logMessage(fqcn, level, marker, message, throwable); }

logMessage鏄竴涓娊璞℃柟娉曪紝鍏蜂綋瀹炵幇绫绘湁AsyncLogger锛孡ogger绛夛紝鏈鍏堝垎鏋愬悓姝ョ殑Logger绫讳腑鐨刲ogMessage鏂规硶銆?/p>

Logger.logMessage()鏂规硶

public void logMessage(final String fqcn, final Level level, final Marker marker, final Message message, final Throwable t) { final Message msg = message == null ? new SimpleMessage(Strings.EMPTY) : message; final ReliabilityStrategy strategy = privateConfig.loggerConfig.getReliabilityStrategy(); strategy.log(this, getName(), fqcn, marker, level, msg, t); }
public void log(final Supplier<LoggerConfig> reconfigured, final String loggerName, final String fqcn, final Marker marker, final Level level, final Message data, final Throwable t) { loggerConfig.log(loggerName, fqcn, marker, level, data, t); }

loggerConfig.log()鏂规硶

public void log(final String loggerName, final String fqcn, final Marker marker, final Level level, final Message data, final Throwable t) { List<Property> props = null; if (!propertiesRequireLookup) { props = properties; } else { if (properties != null) { props = new ArrayList<>(properties.size()); final LogEvent event = Log4jLogEvent.newBuilder() .setMessage(data) .setMarker(marker) .setLevel(level) .setLoggerName(loggerName) .setLoggerFqcn(fqcn) .setThrown(t) .build(); for (int i = 0; i < properties.size(); i++) { final Property prop = properties.get(i); final String value = prop.isValueNeedsLookup() // since LOG4J2-1575 ? config.getStrSubstitutor().replace(event, prop.getValue()) // : prop.getValue(); props.add(Property.createProperty(prop.getName(), value)); } } } final LogEvent logEvent = logEventFactory instanceof LocationAwareLogEventFactory ? ((LocationAwareLogEventFactory) logEventFactory).createEvent(loggerName, marker, fqcn, requiresLocation() ? StackLocatorUtil.calcLocation(fqcn) : null, level, data, props, t) : //鍒涘缓logEvent瀵硅薄 logEventFactory.createEvent(loggerName, marker, fqcn, level, data, props, t); try { log(logEvent, LoggerConfigPredicate.ALL); } finally { // LOG4J2-1583 prevent scrambled logs when logging calls are nested (logging in toString()) ReusableLogEventFactory.release(logEvent); } }

protected void log(final LogEvent event, final LoggerConfigPredicate predicate) { //鏄惁琚繃婊?/span> if (!isFiltered(event)) { processLogEvent(event, predicate); } }
private void processLogEvent(final LogEvent event, final LoggerConfigPredicate predicate) { event.setIncludeLocation(isIncludeLocation()); if (predicate.allow(this)) { //鎵цappender callAppenders(event); } logParent(event, predicate); }
protected void callAppenders(final LogEvent event) { final AppenderControl[] controls = appenders.get(); //noinspection ForLoopReplaceableByForEach for (int i = 0; i < controls.length; i++) { controls[i].callAppender(event); } }

缁忚繃callAppender鏂规硶鎵ц鍚庯紝鏈€缁堣揪鍒颁笅鏂逛唬鐮侊紝appender鍗充负婊¤冻鏉′欢鐨刟ppender銆?/p>

private void tryCallAppender(final LogEvent event) { try { appender.append(event); } catch (final RuntimeException ex) { handleAppenderError(event, ex); } catch (final Exception ex) { handleAppenderError(event, new AppenderLoggingException(ex)); } }

appender.append()鏂规硶

appender绉嶇被鏈夊绉嶏紝鏈瘒鏂囩珷浠?span class="mq-65">RollingFileAppender涓轰緥

public void append(final LogEvent event) { getManager().checkRollover(event); super.append(event); }
//鏈€缁堟墽琛屼互涓嬫柟娉?/span>private void tryAppend(final LogEvent event) { if (Constants.ENABLE_DIRECT_ENCODERS) { directEncodeEvent(event); } else { writeByteArrayToManager(event); } }protected void directEncodeEvent(final LogEvent event) { //灏唋ogevent杩涜鍔犲瘑澶勭悊 getLayout().encode(event, manager); if (this.immediateFlush || event.isEndOfBatch()) { manager.flush(); } }
public void encode(final StringBuilder source, final ByteBufferDestination destination) { try { final Object[] threadLocalState = getThreadLocalState(); final CharsetEncoder charsetEncoder = (CharsetEncoder) threadLocalState[0]; final CharBuffer charBuffer = (CharBuffer) threadLocalState[1]; final ByteBuffer byteBuffer = (ByteBuffer) threadLocalState[2]; TextEncoderHelper.encodeText(charsetEncoder, charBuffer, byteBuffer, source, destination); } catch (final Exception ex) { logEncodeTextException(ex, source, destination); TextEncoderHelper.encodeTextFallBack(charset, source, destination); } }

3. 鎵╁睍鎬?/span>

LoggerContext鎻愪緵涓€浜涙柟娉曞彲浠ュ姩鎬佺敓鎴愭垨鑰呮敼鍙樹竴浜涘凡閰嶇疆鐨勪俊鎭紝鍏蜂綋鏂规硶鍙傝€冨畼鏂规枃妗c€?/p>

瀹樻柟鏂囨。

http://logging.apache.org/log4j/2.x/log4j-core/apidocs/org/apache/logging/log4j/core/LoggerContext.html

渚?锛氬姩鎬佸垱寤篖ogger鍜孉ppender鑺傜偣

public class LoggerHolder {     public static Logger getLogger(String loggerName) { String loggerName = PREFIX + name; Log4jLoggerFactory loggerFactory = (Log4jLoggerFactory) LoggerFactory.getILoggerFactory(); LoggerContext context = (LoggerContext) LogManager.getContext(); //濡傛灉鏈姞杞借繃璇ogger,鍒欐柊寤轰竴涓?/span> if (loggerFactory.getLoggersInContext(context).get(loggerName) == null) { buildLogger(loggerName); } // return loggerFactory.getLogger(loggerName);    }    //鏂板垱寤轰竴涓猯ogger     private static void buildLogger(String loggerName) {
LoggerContext context = (LoggerContext) LogManager.getContext(); Configuration configuration = context.getConfiguration(); //閰嶇疆PatternLayout杈撳嚭鏍煎紡 PatternLayout layout = PatternLayout.newBuilder() .withCharset(UTF_8) .withPattern("%msg%n") .build(); //閰嶇疆鍩轰簬鏃堕棿鐨勬粴鍔ㄧ瓥鐣?/span> TimeBasedTriggeringPolicy policy = TimeBasedTriggeringPolicy.newBuilder() .withInterval(24) .build(); //閰嶇疆鍚岀被鍨嬫棩蹇楃瓥鐣?/span> DirectWriteRolloverStrategy strategy = DirectWriteRolloverStrategy.newBuilder() .withConfig(configuration) .build(); //閰嶇疆appender RollingFileAppender appender = RollingFileAppender.newBuilder() .setName(loggerName)                .withFilePattern("/data/log/" + loggerName + ".%d{yyyyMMdd}.log") .setLayout(layout) .withPolicy(policy) .withStrategy(strategy) .withAppend(true) .build(); //鏀瑰彉appender鐘舵€?/span> appender.start(); //鏂板缓logger LoggerConfig loggerConfig = new LoggerConfig(loggerName, Level.INFO, false); loggerConfig.addAppender(appender, Level.INFO, null); configuration.addLogger(loggerName, loggerConfig); //鏇存柊context涓婁笅鏂?/span> context.updateLoggers(); }}

渚?锛氬姩鎬佷慨鏀瑰凡鏈塋ogger閰嶇疆椤逛俊鎭紙寰呰皟鐮旓級

閫氳繃鏈嶅姟杩愯鏃剁姸鎬侊紝鍔ㄦ€佷慨鏀归厤缃俊鎭紝鎺у埗鏃ュ織鎵撳嵃锛屼緥濡傦細鏃ュ織闄愭祦锛屾棩蹇楃骇鍒姩鎬佽皟鏁寸瓑銆?/span>

鍙傝€冩枃妗?/h3>

https://www.cnblogs.com/pjfmeng/p/11277124.html http://logging.apache.org/log4j/2.x/log4j-core/apidocs/org/apache/logging/log4j/core/LoggerContext.html

以上是关于log4j2婧愮爜鍒嗘瀽-1的主要内容,如果未能解决你的问题,请参考以下文章

ArrayList婧愮爜鍒嗘瀽

JDK婧愮爜鍒嗘瀽鍒濇鏁寸悊

Memcached婧愮爜鍒嗘瀽涔媔tems.c

婧愮爜鍒嗘瀽涔?--HashMap鏌ユ壘銆佸垹闄ゃ€侀亶鍘?/h1>

绮惧敖 MyBatis 婧愮爜鍒嗘瀽 - SqlSession 浼氳瘽涓?SQL 鎵ц鍏ュ彛

鏁欏コ鏈嬪弸璇绘噦绯诲垪锛歞ubbo鐨勫彲鎵╁睍鏈哄埗SPI 婧愮爜鍒嗘瀽