新系統起步,旨在監控原有系統的各類問題。主要的一部分,就是監視原有系統的日誌。java
日誌,是Java
企業級應用開發必不可少的一部分,市場上有諸多日誌框架。咱們選用slf4j
。服務器
日誌有如下級別:框架
TRACE, DEBUG, INFO, WARN, ERRORide
咱們期待,當系統運行時打印了WARN
或ERROR
級別的日誌時,向咱們的服務器推送消息。使得咱們能夠分析日誌,構造更完整的系統。函數
日誌問題與以前的Hibernate
映射問題不一樣。學習
Hibernate
映射問題是默認用這個類,而後咱們能夠利用Spring Boot
爲咱們提供的配置,當去映射名稱的時候調用我這個類。this
咱們的日誌是這麼寫的:spa
private static final Logger logger = LoggerFactory.getLogger(xxxx.class);
對象都是從LoggerFactory
那建立出來的,咱們根本沒辦法從配置中下手。debug
新建日誌類YunzhiLogger
,去實現org.slf4j.Logger
接口。3d
這是Logger
接口的源碼,一共有61
個方法,咱們一一去實現是不現實的,根據面向對象大法,咱們應該去找一個合適的父類去繼承,而後重寫不符合咱們要求的方法。
package org.slf4j; public interface Logger { final public String ROOT_LOGGER_NAME = "ROOT"; public String getName(); public boolean isTraceEnabled(); public void trace(String msg); public void trace(String format, Object arg); public void trace(String format, Object arg1, Object arg2); public void trace(String format, Object... arguments); public void trace(String msg, Throwable t); public boolean isTraceEnabled(Marker marker); public void trace(Marker marker, String msg); public void trace(Marker marker, String format, Object arg); public void trace(Marker marker, String format, Object arg1, Object arg2); public void trace(Marker marker, String format, Object... argArray); public void trace(Marker marker, String msg, Throwable t); public boolean isDebugEnabled(); public void debug(String msg); public void debug(String format, Object arg); public void debug(String format, Object arg1, Object arg2); public void debug(String format, Object... arguments); public void debug(String msg, Throwable t); public boolean isDebugEnabled(Marker marker); public void debug(Marker marker, String msg); public void debug(Marker marker, String format, Object arg); public void debug(Marker marker, String format, Object arg1, Object arg2); public void debug(Marker marker, String format, Object... arguments); public void debug(Marker marker, String msg, Throwable t); public boolean isInfoEnabled(); public void info(String msg); public void info(String format, Object arg); public void info(String format, Object arg1, Object arg2); public void info(String format, Object... arguments); public void info(String msg, Throwable t); public boolean isInfoEnabled(Marker marker); public void info(Marker marker, String msg); public void info(Marker marker, String format, Object arg); public void info(Marker marker, String format, Object arg1, Object arg2); public void info(Marker marker, String format, Object... arguments); public void info(Marker marker, String msg, Throwable t); public boolean isWarnEnabled(); public void warn(String msg); public void warn(String format, Object arg); public void warn(String format, Object... arguments); public void warn(String format, Object arg1, Object arg2); public void warn(String msg, Throwable t); public boolean isWarnEnabled(Marker marker); public void warn(Marker marker, String msg); public void warn(Marker marker, String format, Object arg); public void warn(Marker marker, String format, Object arg1, Object arg2); public void warn(Marker marker, String format, Object... arguments); public void warn(Marker marker, String msg, Throwable t); public boolean isErrorEnabled(); public void error(String msg); public void error(String format, Object arg); public void error(String format, Object arg1, Object arg2); public void error(String format, Object... arguments); public void error(String msg, Throwable t); public boolean isErrorEnabled(Marker marker); public void error(Marker marker, String msg); public void error(Marker marker, String format, Object arg); public void error(Marker marker, String format, Object arg1, Object arg2); public void error(Marker marker, String format, Object... arguments); public void error(Marker marker, String msg, Throwable t); }
粗略地閱讀了一下LoggerFactory
中getLogger
的源代碼。
裏面有不少的條件,先根據條件獲取ILoggerFactory
,該接口一共有三個實現類,實現類中再去定義不一樣的getLogger
方法,不一樣的工廠獲取出來的日誌對象是不一樣的。
由於對日誌框架不是很瞭解,若是咱們隨便找一個類繼承,那slf4j
的判斷就失去意義了,因此此種方法行不通。
咱們想到了裝飾器模式。
將一個對象進行裝飾,完善其方法。
先將Logger
中的方法都實現掉,而後定義私有變量logger
,定義有參構造函數。
定義logger
用YunzhiLogger
對該日誌對象進行裝飾。
private static final Logger logger = new YunzhiLogger(LoggerFactory.getLogger(xxxx.class));
藉此,也理解了裝飾器模式的應用場景。原來就想,裝飾器實現的功能用繼承不就能實現嗎?爲何還要去裝飾對象呢?直接繼承父類而後調用super
上的方法再加新功能不和這同樣嗎?
如今也明白了,有時候,咱們找不到合適的父類(由於創造出的日誌對象是根據不一樣條件new
不一樣的類創造出來的),而後咱們又想去給這個對象添加方法,沒辦法,只能修飾對象了。
或者有時候,找到父類,可是父類是final
,無法繼承,才用的裝飾器模式。
首先,調用原logger
方法進行默認實現。
package com.mengyunzhi.measurement.log; import org.slf4j.Logger; import org.slf4j.Marker; /** * @author zhangxishuo on 2018/11/15 */ public class YunzhiLogger implements Logger { private Logger logger; public YunzhiLogger(Logger logger) { this.logger = logger; } @Override public String getName() { return this.logger.getName(); } @Override public boolean isTraceEnabled() { return this.logger.isTraceEnabled(); } @Override public void trace(String msg) { this.logger.trace(msg); } @Override public void trace(String format, Object arg) { this.logger.trace(format, arg); } @Override public void trace(String format, Object arg1, Object arg2) { this.logger.trace(format, arg1, arg2); } @Override public void trace(String format, Object... arguments) { this.logger.trace(format, arguments); } @Override public void trace(String msg, Throwable t) { this.logger.trace(msg, t); } @Override public boolean isTraceEnabled(Marker marker) { return this.logger.isTraceEnabled(marker); } @Override public void trace(Marker marker, String msg) { this.logger.trace(marker, msg); } @Override public void trace(Marker marker, String format, Object arg) { this.logger.trace(marker, format, arg); } @Override public void trace(Marker marker, String format, Object arg1, Object arg2) { this.logger.trace(marker, format, arg1, arg2); } @Override public void trace(Marker marker, String format, Object... argArray) { this.logger.trace(marker, format, argArray); } @Override public void trace(Marker marker, String msg, Throwable t) { this.logger.trace(marker, msg, t); } @Override public boolean isDebugEnabled() { return this.logger.isDebugEnabled(); } @Override public void debug(String msg) { this.logger.debug(msg); } @Override public void debug(String format, Object arg) { this.logger.debug(format, arg); } @Override public void debug(String format, Object arg1, Object arg2) { this.logger.debug(format, arg1, arg2); } @Override public void debug(String format, Object... arguments) { this.logger.debug(format, arguments); } @Override public void debug(String msg, Throwable t) { this.logger.debug(msg, t); } @Override public boolean isDebugEnabled(Marker marker) { return this.logger.isDebugEnabled(marker); } @Override public void debug(Marker marker, String msg) { this.logger.debug(marker, msg); } @Override public void debug(Marker marker, String format, Object arg) { this.logger.debug(marker, format, arg); } @Override public void debug(Marker marker, String format, Object arg1, Object arg2) { this.logger.debug(marker, format, arg1, arg2); } @Override public void debug(Marker marker, String format, Object... arguments) { this.logger.debug(marker, format, arguments); } @Override public void debug(Marker marker, String msg, Throwable t) { this.logger.debug(marker, msg, t); } @Override public boolean isInfoEnabled() { return this.logger.isInfoEnabled(); } @Override public void info(String msg) { this.logger.info(msg); } @Override public void info(String format, Object arg) { this.logger.info(format, arg); } @Override public void info(String format, Object arg1, Object arg2) { this.logger.info(format, arg1, arg2); } @Override public void info(String format, Object... arguments) { this.logger.info(format, arguments); } @Override public void info(String msg, Throwable t) { this.logger.info(msg, t); } @Override public boolean isInfoEnabled(Marker marker) { return this.logger.isInfoEnabled(marker); } @Override public void info(Marker marker, String msg) { this.logger.info(marker, msg); } @Override public void info(Marker marker, String format, Object arg) { this.logger.info(marker, format, arg); } @Override public void info(Marker marker, String format, Object arg1, Object arg2) { this.logger.info(marker, format, arg1, arg2); } @Override public void info(Marker marker, String format, Object... arguments) { this.logger.info(marker, format, arguments); } @Override public void info(Marker marker, String msg, Throwable t) { this.logger.info(marker, msg, t); } @Override public boolean isWarnEnabled() { return this.logger.isWarnEnabled(); } @Override public void warn(String msg) { this.logger.warn(msg); } @Override public void warn(String format, Object arg) { this.logger.warn(format, arg); } @Override public void warn(String format, Object... arguments) { this.logger.warn(format, arguments); } @Override public void warn(String format, Object arg1, Object arg2) { this.logger.warn(format, arg1, arg2); } @Override public void warn(String msg, Throwable t) { this.logger.warn(msg, t); } @Override public boolean isWarnEnabled(Marker marker) { return this.logger.isWarnEnabled(marker); } @Override public void warn(Marker marker, String msg) { this.logger.warn(marker, msg); } @Override public void warn(Marker marker, String format, Object arg) { this.logger.warn(marker, format, arg); } @Override public void warn(Marker marker, String format, Object arg1, Object arg2) { this.logger.warn(marker, format, arg1, arg2); } @Override public void warn(Marker marker, String format, Object... arguments) { this.logger.warn(marker, format, arguments); } @Override public void warn(Marker marker, String msg, Throwable t) { this.logger.warn(marker, msg, t); } @Override public boolean isErrorEnabled() { return this.logger.isErrorEnabled(); } @Override public void error(String msg) { this.logger.error(msg); } @Override public void error(String format, Object arg) { this.logger.error(format, arg); } @Override public void error(String format, Object arg1, Object arg2) { this.logger.error(format, arg1, arg2); } @Override public void error(String format, Object... arguments) { this.logger.error(format, arguments); } @Override public void error(String msg, Throwable t) { this.logger.error(msg, t); } @Override public boolean isErrorEnabled(Marker marker) { return this.logger.isErrorEnabled(marker); } @Override public void error(Marker marker, String msg) { this.logger.error(marker, msg); } @Override public void error(Marker marker, String format, Object arg) { this.logger.error(marker, format, arg); } @Override public void error(Marker marker, String format, Object arg1, Object arg2) { this.logger.error(marker, format, arg1, arg2); } @Override public void error(Marker marker, String format, Object... arguments) { this.logger.error(marker, format, arguments); } @Override public void error(Marker marker, String msg, Throwable t) { this.logger.error(marker, msg, t); } }
這是我爲裝飾器添加的默認實現,若有錯誤,歡迎批評指正。
而後就能夠在相應的方法中添加咱們的邏輯,如在error
的方法中向咱們的日誌監控服務推送消息。
slf4j
源碼的學習大體學習了日誌框架slf4j
的運行原理。error
方法與warn
方法有不少重載的方法,因此咱們期待能夠實現對該日誌類中全部名爲error
與warn
的方法進行切面處理。