装饰器的实际应用

本文涉及的产品
日志服务 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
|
Python
一日一技:装饰器如何装饰异步函数
一日一技:装饰器如何装饰异步函数
166 0
|
存储 缓存 关系型数据库
Python装饰器1-闭包与函数装饰器
闭包与函数装饰器:被装饰函数不带参数、被装饰函数带参数、装饰器带参数,装饰器的调用
Python装饰器1-闭包与函数装饰器
|
开发者 Python
装饰器详解|学习笔记
快速学习装饰器详解
|
Python
Python编程:decorator装饰器
Python编程:decorator装饰器
118 0
|
设计模式 JavaScript 前端开发
2021你要知道的前端装饰器(Decorator)
2021你要知道的前端装饰器(Decorator)
670 0
|
设计模式 程序员 Python
Python函数装饰器指南
Python 具有强大的功能和富有表现力的语法。我最喜欢的装饰之一。在设计模式的上下文中,装饰器动态更改方法或类功能,而不必直接使用子类。当您需要扩展功能,但不想修改原函数时,这是理想的选择。我们可以在任何地方实现装饰器模式,但是 Python 通过提供更具表现力的功能和语法来促进实现。
128 0