上犹电脑信息网我们一直在努力
您的位置:上犹电脑信息网 > win7问题 > 怎么找出监听器_crontab执行日志

怎么找出监听器_crontab执行日志

作者:上犹日期:

返回目录:win7问题

内容导航:
  • SpringBoot日志源码解析:日志监听器的执行
  • springboot哪个拦截器 可以做响应数据的日志
  • Springboot jar包后台启动后,日志并没有按天输出,这是为什么?
  • springboot日志在dos下输出中文乱码是什么问题
  • 一、SpringBoot日志源码解析:日志监听器的执行

    LoggingApplicationListener 的执行

    LoggingApplicationListener 的主要作用是配置LoggingSystem, 如果 环境 包含 loggingconfig 属性,LoggingApplicationListener 将用于引导 日志记录系统,否则使用默认配置。


    如果环境包含 logging.level.*和日志记录组,则可以使用 logging.group 定义日志记录级别。


    关于 LoggingApplicationL istener 的重点功能我们后面章节再进行讲解。


    LoggingApplicationListener 实现自 GenericApplicationListener 接口,具有监听器的特性。


    因此,执行 EventPublishingRunListener 广播事件之后,LoggingApplicationListener 便会监听到对应的事件并执行 onApplicationEvent 方法中的逻辑判断,有针对性地处理不同的事件,相关代码如下。


    @Overridepublic void onApplicationEvent(ApplicationEvent event) {if (event instanceof ApplicationStartingEvent) {// springboot 启动时触发onApplicationStartingEvent( (ApplicationStartingEvent) event);} else if (event instanceof ApplicationEnvironmentPreparedEvent) {// Environment 环境准备初级阶段触发onApplicationEnvironmentPreparedEvent( (Applicat ionEnvironmentPrepared-Event) event);} else if (event instanceof ApplicationPreparedEvent) {//应用上下文准备完成,但未刷新时触发onApplicationPreparedEvent( (Applicat ionPreparedEvent) event);else if (event instanceof ContextClosedEvent&& ((ContextClosedEvent) event). getApplicationContext() . getParent() == null) {//容器关闭时处理onContextClosedEvent( );} else if (event instanceof ApplicationFailedEvent) {//启动失败时处理onApplicationFailedEvent();}}

    以上代码中的事件处理基本涵盖了 Spring Boot 启动的不同阶段和不同状况,比如 SpringBoot 刚刚启动阶段、环境准备初级阶段、应用上下文准备完成阶段、容器关闭阶段、应用程序启动失败等。后面章节我们会对这些过程中日志系统是如何处理的进行详解介绍。


    SpringBoot日志源码解析:日志监听器的执行

    ApplicationStartingEvent 事件处理

    在 Spring Boot 的启动过程中,通过 SpringApplicationRunListeners 类间接的调用了EventPublishingRunListener 中 的 各 类 事 件 的 发 布 方 法 , 最 终 被 LoggingApplicationListener 监听并进行处理。在后续的讲解中,我们省略这个中间调用过程,直接讲解 Logging-ApplicationL istener 接收到事件后的处理。


    Spring Boot 刚 刚 启 动 时 发 布 了 ApplicationStartingEvent 事 件 , LoggingApplication-Listener 中的 onApplicationStartingEvent 方法便被调用了,该方法源码如下。


    private void onApplicat ionStartingEvent(ApplicationStartingEvent event)this .loggingSystem = LoggingSystem. get(event . getSpringApplication(). getClassLoader()) ;this. loggingSystem. beforeInitialize();}

    在 onApplicationStartingEvent 方法中,首先获得一个 LoggingSystem 对象,然后调用对象的 beforelnitialize 方 法进行预初始化操作。也就是说在 Spring Boot 开始启动时,日志系统做了两件事:创建 LoggingSystem 对象和预初始化操作。


    LoggingSystem 为日志系统的通用抽象类,其中也提供了获取 LoggingSystem 对象的静态方法。上面 LoggingSystem 的创建便 是调用其 get 方法获得,相关代码如下。


    public static LoggingSystem get(ClassLoader classLoader) {//从系统变量中获得 L oggingSystem 的类名String loggingSystem = System. getProperty(SYSTEM PROPERTY);f (StringUtils . hasLength(loggingSystem)) {if (NONE . equals(loggingSystem))return new NoOpLoggingSystem();/如果存在,则通过反射进行对象的初始化return get(classLoader, loggingSystem);// MSYSTEMS 筛选并初始化 LoggingSystem 对象return SYSTEMS . entrySet() . stream(). filter((entry) -> ClassUtils. isPresent(entry . getKey(), classLoader)).map((entry) -> get(classLoader, entry . getValue())). findFirst(). orElseThrow(() -> new IllegalStateException("No suitable logging system located"));}

    该方法首先判断系统中是否配置了 LoggingSystem 的配置,存在且不为“none”时,则利用反射机制进行初始化;如果明确配置为"none”,则返回 NoOpL oggingSystem 对象。实例化配置的 L oggingSystem 相关代码如下。


    private static LoggingSystem get(ClassLoader classLoader, String loggingSystemClass) {tryClass systemClass = ClassUtils . forName( loggingSystemClass, classLoader);Constructor constructor = systemClass . getDeclaredConstructor(Class-Loader.class);constructor . setAccessible(true);return (LoggingSystem) constructor. newInstance(classLoader);} catch (Exception ex) {throw new IllegalStateException(ex);}}

    以上代码就是通过获取指定类的构造器,调用其 newInstance 方法来创建 LoggingSystem对象的。


    如果系统中不存在该对象的配置,则从 SYSTEMS 筛选获取第一个符合条件的值,然后进行初始化。SYSTEMS 为 L oggingSystem 的静态变量,通过静态代码块进行初始化,相关代码如下。


    private static final Map SYSTEMS;static {Map systems = new LinkedHashMap<>();systems . put("ch. qos . logback. core . Appender""org. springframework . boot . logging . logback. LogbackLoggingSystem");systems . put("org. apache. logging. log4j . core. impl. Log4jContextFactory""org. springframework. boot. logging . log4j2 . Log4J2LoggingSystem");systems . put("java .util. logging. LogManager" ,"org. springframework . boot . logging . java . Javal oggingSystem");SYSTEMS = Collections . unmodifiableMap(systems);}

    常 量 SYSTEMS 是 Map 结 构 , 其 中 key 为 对 应 日 志 系 统 的 核 心 类 ( 类 似@ConditionalOn-Class 注解中指定的类), value 的值 是 LoggingSystem 的具体实现类。


    在静态代码块中,初始化分别添加了 LogbackL oggingSystem、Log4J2L oggingSystem 和JavaLoggingSystem,这也是 Spring Boot 默认内置的 3 个日志实现类。而且 SYSTEMS 被初始化之后便不可被修改了。


    其中从 SYSTEMS 中筛选出符合条件的 L oggingSystem 实现类,这里采用了 Java 8 新增的 Stream 语法来实现,基本处理过程是这样的:遍历 SYSTEMS 中的值,通过 ClassUtils的 isPresent 方 法过滤符合条件的值(key 对应的类存在于 classpath 中) ;然后通过上面提到的反射方法创建筛选过后的值的对象;最后获取第一个对象并返回。如果未获取到则抛出异常。


    由于 SYSTEMS 是基于 LinkedHashMap 实现的,因此,这里可以看出默认情下 SpringBoot优先采用 org.springframework.bot.logging.logback.LogbackL oggingSystem 实现类。


    也就是说,默认情况下使用 L ogback 进行日志配置。


    完成 LoggingSystem 初始化之后,程序便调用其 beforelnitialize 方法进行初始化前的准备工作。在 L oggingSystem 中 beforelnitialize 为抽象方法,由子类实现。该方法在 LogbackLoggingSystem 中的源码实现如下。


    public void beforeInitialize() {//获得 LoggerContextLoggerContext loggerContext = getLoggerContext();//如果 LoggerContext 中已经配置有 oggingSystem 对应的 Logger,则直接返回if (isAlreadyInitialized(loggerContext)) {return;11 调用父类的初始化方法super . beforeInitialize();//向 LoggerContext 中的 TurboFilterL ist 添加 1 个 TurboFilter// 目的是在 L oggerContext 没有初始化之前对应打印的日志的请求全部拒绝loggerContext . getTurboFilterList() . add(FILTER);}

    该方法的主要功能是获得 LoggerContext 并校验是否存在对应的 logger,如果不存在则调用父类的初始化方法,并拒绝在 L oggerContext 没有初始化之前对应打印的日志的全部请求。


    LogbackL oggingSystem 的 父 类 为 SIf4JL oggingSystem, 因 此 方 法 中 调 用 了 SIf4JLogging-System 的 beforelnitialize 方法,相关源码如下。


    public abstract class Slf4JLoggingSystem extends AbstractLoggingSystem {private static final String BRIDGE_ HANDLER = "org. slf4j . bridge . SLF4JBridgeHandler";@Overridepubliic void beforeInitialize()//调用父类的 beforeInitialize, 默认父类实现为空super . beforeInitialize();//配置 jdk 内置日志与 SLF4J 直接的娇接 HandlerconfigureJdkL oggingBridgeHandler();private void configureJdkl oggingBridgeHandler() {//判断是否需要将 JUL 桥接为 SLf4jif (isBridgeJulIntoSlf4j()) {//删除 jdk 内置日志的 HandlerremoveJdk oggingBridgeHandler();//添加 SLF4J 的 HandlerSLF4JBridgeHandler . install();catch (Throwable ex) {//忽略异常。没有 java. util. Logging 桥接被安装}//根据两个条件判断是否将 JUL 桥接为 SLF4Jprotected final boolean isBridgeJulIntoSlf4j() {return isBridgeHandlerAvailable() && isJulUsingASingleConsoleHandler-AtMost();/判断 org. slf4j. bridge. SLF4JBridgeHandler 是否存在于类路径下protected final boolean isBridgeHandlerAvailable()return ClassUtils. isPresent(BRIDGE_ HANDLER, getClassLoader());//判断是否不存在 HandLer 或只存在-个 Consol eHandlerprivate boolean isJulUsingASingleConsoleHandlerAtMost() {Logger rootLogger = LogManager . getLogManager(). getLogger("");Handler[] handlers = rootlogger. getHandlers();return handlers.length == 0 | | (handlers.length == 1 && handlers[0] instanceof-ConsoleHandler);//移除 Handlerprivate void removeJdkL oggingBridgeHandler() {try {removeDefaultRootHandler();//移除 SLF4J 相关 HandlerSLF4JBridgeHandler . uninstall();} catch (Throwable ex) {//忽略并继续//移除 ConsoleHandlerprivate void removeDefaultRootHandler() {try {Logger rootLogger = LogManager . getLogManager().getLogger(" );Handler[] handlers = rootl ogger. getHandlers( );if (handlers.length == 1 && handlers[0] instanceof ConsoleHandler) {rootLogger . removeHandler(handlers[0]);} catch (Throwable ex) {//忽略并继续}}}

    上述代码涵盖了 SIf4JL oggingSystem 中大多数的功能,其主要目的就是处理内置日志(JUL)与 SLF4J 的 Handler 的桥接转换操作。


    基本判断逻辑如下:如果类路径下存在 SLF4JBridgeHandler 类,并且根 Logger 中不包含或仅包含 ConsoleHandler 时,说明需要将内置日志转换为 SLF4J。


    基本转换过程分两步:删除原有 Handler、新增指定的 Handler; 如果满足条件,先删除内置日志的Handler,然后再删除SLF4J的Handler,最后再将SLF4J对应的SLF4JBridgeHandler添加到根 L ogger 中。


    具体的方法实现参考上述代码中的注解,关于 SLF4J 的 uninstall 方法和 install 方法均在SLF4JBridgeHandler 类中,实现比较简单,在此不再进行拓展。不过建议读者朋友阅读一下 SLF4JBridgeHandler 中的源代码, 其内部还提供了转换过程中各层级日志级别对应等处理。


    至此,针对 Spring Boot 启动阶段发出的 ApplicationStartingEvent 事件及日志系统所做的相应操作已经讲解完毕。


    SpringBoot日志源码解析:日志监听器的执行

    ApplicationEnvironmentPreparedEvent 事件处理

    当 SpringBoot 继续启动操作便会广播 ApplicationEnvironmentPreparedEvent 事件,此时便会调用 LoggingApplicationListener 的 onApplicationEnvironmentPreparedEvent 方法,该方法源码如下。


    private void onApplicationEnvironmentPreparedEvent(ApplicationEnvironmentPreparedEvent event) {if (this.loggingSystem == null)this. loggingSystem = LoggingSystem.get(eventgetSpringApplication()initialize(event. getEnvironment(), event . getSpringApplication(). getClassLoader());}

    在上一节中,ApplicationStartingEvent 事件触发时 ,loggingSystem 已经初始化赋值了,在该方法中会再次判断loggingSystem是否为null,如果为null,则通过LoggingSystem的 get方法进行对象创建。


    完成 loggingSystem 的再次判断并创建之后,调用 initialize 方法进行初始化操作,主要完成了初始参数的设置、日志文件、日志级别设置以及注册 ShutdownHook 等操作,相关代码如下。


    protected void initialize(ConfigurableEnvironment environment, ClassLoaderclassLoader) {//创建 LoggingSystemProperties 对象,并 没置默认属性new LoggingSystemProperties( environment) . apply();//获取 LogFile,如果 LogFile 存在, 则向系统属性写入 LogFile 配置的文件路径this.logFile = LogFile . get( environment);if (this.logFile != null) {this . logFile . applyToSystemProperties();this. loggerGroups = new LoggerGroups(DEFAULT_ GROUP_ LOGGERS);!1 rsrinooogginginitializeEarlyLoggingL evel(environment);//初始化 L oggingSysteminitializeSystem(environment, this . loggingSystem, this. logFile);//最终没置日志級别initializeFinaloggingL evels(environment, this . loggingSystem) ;//注册 ShutdownHookregisterShutdownHookIfNecessary(environment, this . loggingSystem);}

    上述代码中,创建 LoggingSystemProperties 对象之 后主要是通过调用其 apply 方法来获取默认的日志配置参数(在配置文件中以"logging.”开头的属性),并设置到系统属性中。


    LogFile的get方法主要是获取日志文件的路径和名称,并作为参数创建Logfile对象。LogFile中 get 方法相关代码如下。


    public static LogFile get(PropertyResolver propertyResolver) {Strinp file = petI OpFi ] ePronertv( nronertvResolver. FTI F NAMF PROPERTY. F TLE_ PROPERTY);String path = getLogFileProperty(propertyResolver, FILE_ PATH PROPERTY, PAif (StringUtils.haslength(file) | StringUtils.haslength(path)) {return new LogFile(file, path);}return null;}

    从上述代码可以看出,通过获取属性名为"logging.ile.path"的值得到了 日志的路径,通过获取属性名为"logging.file.name "的值得到了日志文件名。其中 getLogFileProperty 的第 3 个参数为兼容历史版本中的配置属性名。当然,程序会优先获取当前版本的属性配置,当查找不到值时才会获取历史版本的值。


    紧接着,initialize 方法中判断当 LogFile 不为 null 时,调用它的 apply ToSystemProperties方法,也就是将上述获得的日志文件路径和名称存入系统属性当中。


    initializeEarlyL oggingl .evel 方法用于早期设置 springBootl ogging 的值和 LoggingSystem的初始化,代码如下。


    private void initializeEarlyLoggingl evel (Conf igurableEnvironment environmenif (this. parseArgs && this . springBootLogging == null) {f (isSet(environment, "debug")) {this . springBootLogging = LogLevel. DEBUG;this. springBootlogging = Loglevel. TRACE;}}}

    上述代码主要根据 parseArgs 参数(默认为 true )和 springBootLogging 是否为 null,在早期阶段中设置 springBootL ogging 的值,也就是日志级别。


    在 parseArgs 为 true, 并 且 springBootLogging 值 为 null 的 情 况 下 , 如 果Configurable-Environment 中 debug 的值存在且为 true, 则设置 springBootL ogging 为DEBUG。同样,如果 trace 的值存在且为 true,则设置 springBootLogging 为 TRACE。


    初始化 LoggingSystem 的代码如下。


    private void initializeSystem(Conf igurableEnvironment environment,LoggingSystem system, LogFile logFile) {//实例化 LoggingInitial izat ionContextLoggingInitializationContext initializationContext = new LoggingInitializationContext (environment);String 1ogConfig 二 enviroment .getProperty(CONFITG PROPERTY);if (ignoreLogConfig(logConfig))//如果 logging. config 没有配置或者配置的值是 D 开头的,则调用 L oggingSystem的方法进行初始化system . initialize(initializationContext, null, logFile);} else {11 通过 ResourceUtils 进行加载判断其文件是否存在,如果不存在,则抛出 IllegalStateExceptionResourceUtils .getURL(logConfig) .openStream().close();//存在则调用 L oggingSystem 的方法进行实例化system. initialize(initializationContext, logConfig, logFile);} catch (Exception ex) {private boolean ignoreLogConfig(String logConfig) {return !StringUtils.hasLength(logConfig) 11 logConfig. startsWith("-D");}

    initializeSystem 方法中代码的逻辑主要是围绕 L oggingSystem 的初始化来进行的,首先为其初始化准备了 LogginghitializationContext 对象。然后获取 logging.config 的参数并赋值给 logConfig,如果 logConfig 未配置 或者配置的值以 D 开头,则调用 LoggingSystem 的initialize 方法进行初始化; 其他情况则通过 ResourceUtil 加载判断对应配置文件是否存在,如果不存在,则抛出llegalStateException;如果存在,则同样调用L oggingSystem的initialize方法进行初始化。


    下面我们来看 LoggingSystem 的 itialize 方法的源代码。该方法在 LoggingSystem 类中的实现为空,而在其子类 AbstractL oggingSystem 中提供了如下的实现。


    @Overridepublic void initialize(LoggingInitializationContext initializationContext,String configLocation, LogFile logFile) {if (StringUtils . hasLength(configLocation))initializeWi thSpecificConfig(initializationContext, configLocation, logFile);return;}initializeWithConvent ions (initializationContext, logFile);}

    .上述代码中,如果用户指定了配置文件,则加载指定配置文件中的属性进行初始化操作;如果未指定配置,则加载默认的配置,比如 log4j2 的 log4j2 .properties 或 log4j2.xml。其中默认加载日志配置文件名称及文件格式由具体的子类实现。


    下面重点讲解 SpringBoot 中默认查找配置文件路径的实现,该部分在 LoggingSystem的抽象子类 AbstractL oggingSystem 的 initializeWithConventions 中实现。


    private void initializeWithConventions(LoggingInitializationContext initializationContext, LogFile logFile)String config = getSelfInitializat ionConfig();if (config != null && logFile == null) {//自我初始化操作,属性变更时会重新初始化reinitialize(initializationContext);return;}if (config == null) {config = getSpringInitializationConfig();}if (config != null) {loadConfiguration(initializationContext, config, logFile);return;loadDefaults(initializationContext, logFile);}

    该方法的基本流程是:首先,获得默认的日志配置文件(比如 logback.xml 等), 当配置文件不为 null,且 logFile 为 null 时, 进行自我初始化,具体实现由不同的日志框架来执行,主要就是重置数据并加载初始化;然后,如果默认的配置文件不存在,则尝试获取包含“-spring”的名称的配置文件(比如 logback-spring.xmI 等),如果获得对应的配置文件,则直接加载初始化;最后,如果上述两种类型的配置文件均未找到,则调用 loadDefaults 方法采用默认值进行加载配置。


    getSelflnitializationConfig 方法和 getSpringlnitializationConfig 都是用来获取默认配置文件名称的,不同之处在于获得的配置文件的名称中是否多了“一 spring"。这两个方法都是先调用 getStandardConfig ocations 方法获得默认的配置文件名称数组,然后再调用 findConfig来验证获取符合条件的值。


    我们先看不同之处,getSpringhnitializationConfig 方法通过 getSpringConfigL ocations 来获得配置文件名称数组。


    protected String[] getSpringConfigLocations() {//获得默认配置文件的路径String[] locations = getStandardConfigLocations();for (int i = 0; i < locations.length; i++) {String extension = StringUtils. getFilenameExtens ion(locations[i]);locations[i] = locations[i]. substring(0,locations[i].length() - extension.1ength() - 1) + "-spring.t extension;return locations;}

    上述代码中,通过 getStandardConfigLocations 获得 了默认配置文件名称数组,然后对路径中的文件名进行兼容处理,比如默认配置文件名称为 logback.xml ,当我们配置为logback-spring.xml 时 , 通 过 getSelfInitializationConfig 方 法 无 法 加 载 到 , 但 通 过getStandard-ConfigLocations 方法则可以加载到。上述方 法核心处理就是将默认的配置文件名截取之后拼接上了“-spring"。


    其中两个方法都调用了 getStandardConfigLocations 方法为 AbstractLoggingSystem 的抽象方法,具体实现由具体日志框架的子类来完成,比如在 L ogbackL oggingSystem 中,该方法的实现如下。


    protected String[] getStandardConfigLocations() {return new String[] { "logback- test . groovy", "logback-test . xml", "logback. groovy""logback.xml" };}

    也就是说,LogbackLoggingSystem 默认支持以 logback-test.groovy、logback-test.xml、logback.groovy、logback.xm 以及 上述名称扩展了“-spring”(比如 logback-spring.xml)的配置文件。


    无论是通过配置指定配置文件名称,还是通过上述默认方式获得配置文件名称,当获得之后,都会调用 loadConfiguration 方法进行配置的加载。loadConfiguration 方法由子类来实现,比如,LogbackLoggingSystem 中实现的源码如下。


    @Overrideprotected void loadConfiguration(LoggingInitializat ionContext initializatString location, LogFile logFile) {super . loadConfiguration(initializationContext, location, logFile);//获得 LoggerContext, 这里实际上是 ILoggerFac tory 的具体实现LoggerContext loggerContext = getLoggerContext();stopAndReset(loggerContext);configureByResourceUrl(initializationContext, loggerContext,} catch (Exception ex) {ResourceUtils.getURL(location));}}}

    上述代码中首先会调用父类的 loadConfiguration 方法,该方法的最终操作还是调用了前面讲到的 LoggingSystemProperties#apply 方法进行参数的获取,并设置到系统属性中。


    getL oggerContext 获得了 LoggerContext 对象,本质上 LoggerContext 是 ILoggerFactory的具体实现类。随后通过 stopAndReset 方法对日志相关的参数、监听器等进行停止和重置。


    configureByResourceUrl 方法重点实现了针对 xml 格式的配置文件和其他格式(比如 groovy后缀)的配置文件的解析和具体配置,相关操作由对应的日志框架内部提供的类来实现。


    最 后 , 再 回 到 AbstractL oggingSystemtinitializeWithConventions 方 法 中 调 用 的IloadDefaults 方法,看看当未查找到配置文件时是如何处理的。


    loadDefaults 方法同样是抽象方法,在 LogbackLoggingSystem 中的具体实现如下。


    @Overrideprotected void loadDefaults(LoggingInitializationContext initializationContext, LogFile//获得 L oggerContext(ILoggerFactory)并进行重置操作secrerecntxt BetLossercontext();//获得是否为 debug 模式boolean debug = Boolean.getBoolean("logback. debug");//如果为 debug 模式则添加控制台监听器StatusL istenerConfi gHelper . addOnConsoleL istenerInstance(context, new OnStatuslistener//根据是否为 debug 模式创建不同的 L ogbackConfiguratorLogbackConfigurator configurator = debug ? new Debugl ogbackConfigurator(c: new LogbackConfigurator(context);i 配置白志级别将( LEVEL PATTERNE 默认 5setnmironomnticontext . putProperty(LoggingSystemProperties.L0G_ LEVEL_ PATTERN,environment . resolvePlaceholders("${logging. pattern.level:${LOG_ LEVEL_PATTERN:%5p}}"));//配置日志中时间格式(LOG DATEFORMAT_ PATTERN), 默认为 y>y -M-dd HH: m:ss.sssSoggingSystemProperties.LOGDATEFORMAT_PATTERN,environment.resolvePlacehold0BB1"${logging . pattern.dateformat:${LOG_ DATEFORMAT_ PATTERN:yyy-MM-dd HH:m.SS}"));//配置文件名称格式(ROLLING FILE_ _NAME_ PATTERN),默认为${LOG _FILE}. %d{yyy -MM-dd}. %i.gz}(logingSystemProperties . RLLING FILE NANE PATTERN, environment.resolvePlaceholders("${logging. pattern. rolling-file-name:${LOG_ FILE} .%yy--d}- .%i.g}));new DefaultLogbackConfiguration(initializationContext, logFile). apply(configurator);context . setPackagingDataEnabled(true);}

    以 上 代 码 主 要 进 行 了 LoggerContext 重 置 、 日志输出格 式 、 日志文 件 名 、Logback-Configurator (编程风格配置 logback)等设置,具体操作的作用可对照上述代码中的注解进行了解。


    回到最初 L oggingApplicationListener 的 initializeSystem 方法,值得注意的是,在通常情况下,该方法中往往不是直接采用 LoggingSystem 的抽象类 AbstractL oggingSystem 中的initialize 方法实现,而是通过不同日志框架重新实现,在恰当的时机会调用 AbstractL oggingSystem 的 initialize 方法。这样做的好处是可以根据不同的日志框架进行定制化的扩展。比如LogbackL oggingSystem 中 initialize 方法的实现如下。


    @Overridepublic void initialize(LoggingInitializationContext initializationContexString configLocation, LogFile logFile) {LoggerContext loggerContext = getLoggerContext();if (isAlreadyInitialized(loggerContext)) {return;super. initialize(initializationContext, configLocation, logFile);loggerContext. getTurboFilterList() . remove(FILTER);markAsInitialized(loggerContext);if (StringUtils. hasText(System. getProperty (CONFIGURATION_ FILE_ PROPERTY))){getLogger(LogbackL oggingSystem. class . getName()) .warn("Ignoring '” + CONFIGURATION_ FILE_ PROPERTY +”' system property.'+ "Please use ' logging. config' instead.");}}

    我们可以看到,在 LogbackL oggingSystem 的实现类中不仅在调用父类的 initialize 方法之前进行了是否已经初始化的判断,还在调用父类 initialize 方法之后,实现了它自己的一些业务逻辑,比如移除 LoggerContext 的 TurboFilterList 中添加的 TurboFilter、标记初始化状态。


    在完成了以上步骤之后,日志系统已经正式启动,可以进行正常的日志输至此,针 对 LoggingApplicationListener 中 ApplicationEnvironmentPreparedEvent 事件的处理已经讲解完毕。


    SpringBoot日志源码解析:日志监听器的执行

    小结

    本章详细介绍了 Spring Boot 启动过程中日志事件的触发,以及事件发布之后,日志系统所对应的处理。在 LoggingApplicationListener 的 onApplicationEvent 方法中还有其他事件的处理,比如:


    ApplicationPreparedEvent、ContextClosedEvent 、ApplicationFailedEvent 等,但相对于上述过程,这些事件的日志处理比较简单,读者可自行阅读。当然,如果对日志系统感兴趣,可针对具体的技术框架进行更加深入地学习。


    本文给大家讲解的内容是Spring Boot日志源码解析:LoggingApplicationListener的执行
    1. 下篇文章给大家讲解的是创建SpringBoot自动配置项目;
    2. 觉得文章不错的朋友可以转发此文关注小编;
    3. 感谢大家的支持!

    二、springboot哪个拦截器 可以做响应数据的日志

    web.xml面配置 拦截所请求

    spring-mvc
    org.springframework.web.servlet.DispatcherServlet

    contextConfigLocation
    classpath:spring-mvc.xml

    1

    spring-mvc
    /

    三、Springboot jar包后台启动后,日志并没有按天输出,这是为什么?

    又两种方式一个是通过application.properties 配置文件的方式来配置。 另一种是通过logback.xml配置文件的方式进行配置。 首先要说的是:application.properties 和logback.xml这两个配置文件都是放在 src/main/resources 目录下的。

    四、springboot日志在dos下输出中文乱码是什么问题

    进DOS下 输入SET命令 看环境变量 JAVA的路径 UNIX下就输入ENV 直接写路径

    相关阅读

    • 手机云桌面_桌面云免费

    • 上犹win7问题
    • 内容导航: 最全整套企业云桌面(Citrix+XenAppamp;XenDesktop)部署手册 我想知道 citrix 4,citrix4.5 和xenapp xendesktop xenserver 这几个有什么区别?越详细越好~~~ citrix xenapp6.0那里有下啊!谢谢!
    • 怎么找出监听器_crontab执行日志

    • 上犹win7问题
    • 内容导航: SpringBoot日志源码解析:日志监听器的执行 springboot哪个拦截器 可以做响应数据的日志 Springboot jar包后台启动后,日志并没有按天输出,这是为什么? springboot日志在dos下输出
    • 部署k8s_k8s部署hDFS

    • 上犹win7问题
    • 内容导航: Rancher快速部署k8s集群 如何在Kubernetes上进行微服务部署 k8s部署fabric,用minikube部署的k8s集群环境,kube-dns出现了问题 如何在K8S平台部署微服务 一、 Rancher快速部署k8s集群 介绍
    • win7开机logo后黑屏_windows7

    • 上犹win7问题
    • 内容导航: 解决win7共享打印机出现错误0x000006d9小技巧 错误0x000006d9怎么办windows7打印机共享错误0x000006d9如何解决 win7无法共享打印机错误0x000006d9 win7共享打印机提示0x000006d9怎么办 一、
    • uefi u盘_u盘uefi是什么意思

    • 上犹win7问题
    • 内容导航: 电脑BIOS设置优盘启动教程——新uefi bios通用设置 如何设置uefiBios从优盘启动 UEFI的BIOS怎么设置U盘启动?急求!!! uefi bios 如何设置u盘启动 一、 电脑BIOS设置优盘启动教程—
    • 蓝屏出现0x000000ed_xp蓝屏0x000000ed

    • 上犹win7问题
    • 内容导航: win10蓝屏代码0x000000ed的修复方法 win10开机蓝屏提示:0xc000021a 自动自动修复失败…一直重启 求解…急急急 安装Win10系统蓝屏错误代码0xc000000e怎么办 开机出现蓝屏STOP:0*000000E
    • win7正式停更_windows10什么停更

    • 上犹win7问题
    • 内容导航: Win7停更当天,有黑客来“捣乱” 黑客捣乱我就让他她的计算机彻底废掉你觉得行了吧! 刚装的win7过了两天系统就提示有好多高危漏洞这是怎么了??不修复电脑有没有事
    • 90后这代人_90后能人

    • 上犹win7问题
    • 内容导航: 90后第一次接触Windows98,20多年了,居然还有人使用 快20年了,Windows 98系统设备还能使用吗 Windows98依然有人坚持在使用,究竟是哪些行业还需要这个系统呢? 现在还有人用
    • 基金份额确认_Windows7

    • 上犹win7问题
    • 内容导航: Windows系统份额超过90% Win7仍是主流 现在是用win8.1系统的人多?还是用win7系统的人多? 要买笔记本电脑了,请问win7系统落后吗?还是说现在win7还是主流 微软为什么要在20
    • 老子是现在哪里人_李耳老子

    • 上犹win7问题
    • 内容导航: 《老子》春秋李耳 《老子》究竟是谁,李耳这个名字是不是老子的 道家代表人物李聃(李耳)为什么会被称为老子?“老”这个字在 春秋战国时代 有什么意思? 春秋战国
    关键词不能为空
    极力推荐

    电脑蓝屏_电脑怎么了_win7问题_win10问题_设置问题_文件问题_上犹电脑信息网

    关于我们