装饰器的实际应用

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
简介: 使用装饰器模式改造slf4j打印json格式日志

上一篇文章中总结了装饰器模式,现在将装饰器结合实际应用起来。

使用装饰器模式改造slf4j打印json格式日志,以便于日志的分析


一、准备

装饰器模式得有一个抽象组件Component

这里的抽象组件可以直接是org.slf4j.Loggerorg.slf4j.LoggerFactory#getLogger(java.lang.Class)可以看作是一个具体组件(Concrete Component)

还缺少装饰器(Decorator)具体组件(Concrete Decorator)

二、实现

2.1 装饰器JsonLoggerDecorator

publicclassJsonLoggerDecoratorimplementsLogger {
protectedfinalLoggerlogger;
publicJsonLoggerDecorator(Loggerlogger) {
this.logger=logger;
    }
@OverridepublicStringgetName() {
returnnull;
    }
@OverridepublicbooleanisTraceEnabled() {
returnfalse;
    }
@Overridepublicvoidtrace(Stringmsg) {
    }
@Overridepublicvoidtrace(Stringformat, Objectarg) {
    }
@Overridepublicvoidtrace(Stringformat, Objectarg1, Objectarg2) {
    }
@Overridepublicvoidtrace(Stringformat, Object... arguments) {
    }
@Overridepublicvoidtrace(Stringmsg, Throwablet) {
    }
@OverridepublicbooleanisTraceEnabled(Markermarker) {
returnfalse;
    }
@Overridepublicvoidtrace(Markermarker, Stringmsg) {
    }
@Overridepublicvoidtrace(Markermarker, Stringformat, Objectarg) {
    }
@Overridepublicvoidtrace(Markermarker, Stringformat, Objectarg1, Objectarg2) {
    }
@Overridepublicvoidtrace(Markermarker, Stringformat, Object... argArray) {
    }
@Overridepublicvoidtrace(Markermarker, Stringmsg, Throwablet) {
    }
@OverridepublicbooleanisDebugEnabled() {
returnfalse;
    }
@Overridepublicvoiddebug(Stringmsg) {
    }
@Overridepublicvoiddebug(Stringformat, Objectarg) {
    }
@Overridepublicvoiddebug(Stringformat, Objectarg1, Objectarg2) {
    }
@Overridepublicvoiddebug(Stringformat, Object... arguments) {
    }
@Overridepublicvoiddebug(Stringmsg, Throwablet) {
    }
@OverridepublicbooleanisDebugEnabled(Markermarker) {
returnfalse;
    }
@Overridepublicvoiddebug(Markermarker, Stringmsg) {
    }
@Overridepublicvoiddebug(Markermarker, Stringformat, Objectarg) {
    }
@Overridepublicvoiddebug(Markermarker, Stringformat, Objectarg1, Objectarg2) {
    }
@Overridepublicvoiddebug(Markermarker, Stringformat, Object... arguments) {
    }
@Overridepublicvoiddebug(Markermarker, Stringmsg, Throwablet) {
    }
@OverridepublicbooleanisInfoEnabled() {
returnfalse;
    }
@Overridepublicvoidinfo(Stringmsg) {
    }
@Overridepublicvoidinfo(Stringformat, Objectarg) {
    }
@Overridepublicvoidinfo(Stringformat, Objectarg1, Objectarg2) {
    }
@Overridepublicvoidinfo(Stringformat, Object... arguments) {
    }
@Overridepublicvoidinfo(Stringmsg, Throwablet) {
    }
@OverridepublicbooleanisInfoEnabled(Markermarker) {
returnfalse;
    }
@Overridepublicvoidinfo(Markermarker, Stringmsg) {
    }
@Overridepublicvoidinfo(Markermarker, Stringformat, Objectarg) {
    }
@Overridepublicvoidinfo(Markermarker, Stringformat, Objectarg1, Objectarg2) {
    }
@Overridepublicvoidinfo(Markermarker, Stringformat, Object... arguments) {
    }
@Overridepublicvoidinfo(Markermarker, Stringmsg, Throwablet) {
    }
@OverridepublicbooleanisWarnEnabled() {
returnfalse;
    }
@Overridepublicvoidwarn(Stringmsg) {
    }
@Overridepublicvoidwarn(Stringformat, Objectarg) {
    }
@Overridepublicvoidwarn(Stringformat, Object... arguments) {
    }
@Overridepublicvoidwarn(Stringformat, Objectarg1, Objectarg2) {
    }
@Overridepublicvoidwarn(Stringmsg, Throwablet) {
    }
@OverridepublicbooleanisWarnEnabled(Markermarker) {
returnfalse;
    }
@Overridepublicvoidwarn(Markermarker, Stringmsg) {
    }
@Overridepublicvoidwarn(Markermarker, Stringformat, Objectarg) {
    }
@Overridepublicvoidwarn(Markermarker, Stringformat, Objectarg1, Objectarg2) {
    }
@Overridepublicvoidwarn(Markermarker, Stringformat, Object... arguments) {
    }
@Overridepublicvoidwarn(Markermarker, Stringmsg, Throwablet) {
    }
@OverridepublicbooleanisErrorEnabled() {
returnfalse;
    }
@Overridepublicvoiderror(Stringmsg) {
    }
@Overridepublicvoiderror(Stringformat, Objectarg) {
    }
@Overridepublicvoiderror(Stringformat, Objectarg1, Objectarg2) {
    }
@Overridepublicvoiderror(Stringformat, Object... arguments) {
    }
@Overridepublicvoiderror(Stringmsg, Throwablet) {
    }
@OverridepublicbooleanisErrorEnabled(Markermarker) {
returnfalse;
    }
@Overridepublicvoiderror(Markermarker, Stringmsg) {
    }
@Overridepublicvoiderror(Markermarker, Stringformat, Objectarg) {
    }
@Overridepublicvoiderror(Markermarker, Stringformat, Objectarg1, Objectarg2) {
    }
@Overridepublicvoiderror(Markermarker, Stringformat, Object... arguments) {
    }
@Overridepublicvoiderror(Markermarker, Stringmsg, Throwablet) {
    }
}

2.2 具体装饰器JsonLogger

importcom.alibaba.fastjson.JSONObject;
importorg.slf4j.Logger;
importjava.util.Arrays;
publicclassJsonLoggerextendsJsonLoggerDecorator {
publicJsonLogger(Loggerlogger) {
super(logger);
    }
@Overridepublicvoidinfo(Stringmsg) {
JSONObjectjsonObject=this.newJsonObject();
jsonObject.put("message", msg);
logger.info(jsonObject.toJSONString());
    }
@Overridepublicvoiderror(Stringmsg) {
JSONObjectjsonObject=this.newJsonObject();
jsonObject.put("message", msg);
logger.error(jsonObject.toJSONString());
    }
/*** 重载一个异常的error** @param e*/publicvoiderror(Exceptione) {
JSONObjectjsonObject=this.newJsonObject();
jsonObject.put("name", e.getClass().getName());
StringstackTrace=Arrays.toString(e.getStackTrace());
jsonObject.put("stackTrace", stackTrace);
logger.error(jsonObject.toJSONString());
    }
privateJSONObjectnewJsonObject() {
returnnewJSONObject();
    }
}

三、使用

Logger对外提供了一个工厂LoggerFactory,这里我们也提供一个JsonLoggerFactory

importorg.slf4j.Logger;
importorg.slf4j.LoggerFactory;
publicclassJsonLoggerFactory {
publicstaticJsonLoggergetJsonLogger(Class<?>clazz) {
Loggerlogger=LoggerFactory.getLogger(clazz);
returnnewJsonLogger(logger);
    }
}

四、测试类

publicclassJsonLoggerTest {
privatestaticfinalJsonLoggerlogger=JsonLoggerFactory.getJsonLogger(JsonLoggerTest.class);
publicstaticvoidmain(String[] args) {
logger.info("info日志");
logger.error("系统异常");
logger.error(newException("抛出异常"));
    }
}

4.1 执行结果

10:30:31.368 [main] INFO com.example.validated.design.decorator.logger.JsonLoggerTest - {"message":"info日志"}
10:30:31.372 [main] ERROR com.example.validated.design.decorator.logger.JsonLoggerTest - {"message":"系统异常"}
10:30:31.372 [main] ERROR com.example.validated.design.decorator.logger.JsonLoggerTest - {"name":"java.lang.Exception","stackTrace":"[com.example.validated.design.decorator.logger.JsonLoggerTest.main(JsonLoggerTest.java:13)]"}

五、类图

image.png

六、其他

在实际的开发过程,我们也可以通过装饰器模式实现不同角色的用户去展示不同的导航菜单

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
目录
相关文章
装饰器:装饰器为主,闭包和高阶函数为辅
装饰器:装饰器为主,闭包和高阶函数为辅
|
3月前
|
测试技术 Python
装饰器
【8月更文挑战第1天】
20 2
|
6月前
|
JavaScript
03_装饰器
03_装饰器
65 1
|
6月前
22_自定义装饰器
22_自定义装饰器
116 0
|
Python
一日一技:装饰器如何装饰异步函数
一日一技:装饰器如何装饰异步函数
165 0
|
存储 JavaScript 前端开发
装饰器语法
利用typeof判定类型的取值范围是:'undefined' /'boolean' /'string' /'number' /'object' /'function' /'symbol' 在JavaScript内部使用typeof判断类型依据的是二进制,根据变量的机器码低位1-3位存储其类型信息,有如下规则:
111 0
|
存储 缓存 关系型数据库
Python装饰器1-闭包与函数装饰器
闭包与函数装饰器:被装饰函数不带参数、被装饰函数带参数、装饰器带参数,装饰器的调用
Python装饰器1-闭包与函数装饰器
|
开发者 Python
装饰器详解|学习笔记
快速学习装饰器详解
|
Python
Python编程:decorator装饰器
Python编程:decorator装饰器
118 0