新系统起步,旨在监控原有系统的各类问题。主要的一部分,就是监视原有系统的日志。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
的方法进行切面处理。