/**
* Enhances a Class by allowing it to contain Filters.
*/
public abstract class AbstractFilterable extends AbstractLifeCycle implements Filterable
毋庸置疑,首先应该想到的是Appender,所以看官方文档,有哪些Appender。此时的我,都不知道为何getLogger的时候要传入这个类,也可以传入一个字符串,还有Log4J是如何将写日志的操作,日志等级,处理各式各样的配置文件,日志过滤器,日志格式输出,日志输出目的地这些组合在一起的。要实现这些功能,应该把哪些动作归属到同一层级,又如何划分层级呢?
现在我了解到,
每一个Logger都对应一个LoggerConfig;
你可以给Logger在代码动态的添加’配置’;
Log4J有两个包,一个是core包,一个是api包
当前的理解:api-jar包里面定义了很多操作接口,还有一些实体的抽象定义
api-jar包中,比如org.apache.logging.log4j.Logger是对Logger的最基本属性的抽象定义,
core-jar中,是对api中定义的一些接口的实现,它就实现了Logger,这让我想起了HttpClosableClient
生命周期的概念
https://stackoverflow.com/questions/38241654/how-to-add-appender-to-logger-in-log4j2
给当前的logger添加一个Appender,调用API方法,Appender中有个Appender叫WriterAppender
http://logging.apache.org/log4j/2.x/manual/customconfig.html#AddingToCurrent
关键代码复制过来:
final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
final Configuration config = ctx.getConfiguration();
Layout layout = PatternLayout.createLayout(PatternLayout.SIMPLE_CONVERSION_PATTERN, config, null,
null,null, null);
Appender appender = FileAppender.createAppender("target/test.log", "false",
"false", "File", "true",
"false", "false", "4000", layout, null, "false", null, config);
appender.start();
config.addAppender(appender);
AppenderRef ref = AppenderRef.createAppenderRef("File", null, null);
AppenderRef[] refs = new AppenderRef[] {ref};
LoggerConfig loggerConfig = LoggerConfig.createLogger(
"false", "info", "org.apache.logging.log4j",
"true", refs, null, config, null );
loggerConfig.addAppender(appender, null, null);
config.addLogger("org.apache.logging.log4j", loggerConfig);
ctx.updateLoggers();
}
下面我最后改写的,上面代码在IDE下不一定能通过:
Logger targetLogger = LogManager.getLogger();
StringWriter stringWriter = new StringWriter();
@Test
public void testLog4J2(){
targetLogger.info("初始化测试");
log4j2();
targetLogger.info("添加完成");
System.out.println(stringWriter.toString());
}
public void log4j2(){
final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
final Configuration config = ctx.getConfiguration();
PatternLayout layout = PatternLayout.newBuilder().
withCharset(Charset.defaultCharset()).
withPattern("这是我的layout %m").
withConfiguration(config).build();
/* Appender appender = FileAppender.createAppender("target/test.log", "false", "false", "File", "true",
"false", "false", "4000", layout, null, "false", null, config); */
Appender appender = WriterAppender.createAppender(layout, null, stringWriter,
targetLogger.getName(), true, false);
appender.start();
config.addAppender(appender);
AppenderRef ref = AppenderRef.createAppenderRef("File", null, null);
AppenderRef[] refs = new AppenderRef[] {ref};
LoggerConfig loggerConfig = LoggerConfig.createLogger(true, Level.INFO,
targetLogger.getName(), "true", refs, null,
config, null); /* 第一个参数,是否作为附加Appender,否则就只剩新加的Appender */
loggerConfig.addAppender(appender, null, null);
config.addLogger(targetLogger.getName(), loggerConfig); /* 第一个参数,目的Logger名字 */
ctx.updateLoggers();
}