如何看源码及原理分析 原理及源码查看是相辅相成。只能了解原理才能更好的了解源码;只有相应的了解源码才能知道是怎么原理实现。
原理:
	自已设计一个。配合源码查看,验证框架设计者是怎么设计的。
源码:
	只要知道入口。使用时分几步。分别查看。
logback简单使用 加入依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <dependencies >      <dependency >          <groupId > org.slf4j</groupId >          <artifactId > slf4j-api</artifactId >          <version > 1.7.25</version >      </dependency >      <dependency >          <groupId > ch.qos.logback</groupId >          <artifactId > logback-core</artifactId >          <version > 1.1.11</version >      </dependency >      <dependency >          <groupId > ch.qos.logback</groupId >          <artifactId > logback-classic</artifactId >          <version > 1.1.11</version >      </dependency > </dependencies > 
 
使用:
1 2 3 4 5 6 7 8 public  class  Test  {     public  static  void  main (String[] args)  {         Logger  logger  =  LoggerFactory.getLogger(Test.class);         logger.debug("Hello world." );     } }
 
这时运行会在控制台打印日志。
程序在IO上会有标准输入、标准输出、错误输出。
配置文件 logback.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 <configuration >      <appender  name ="FILE"  class ="ch.qos.logback.core.FileAppender" >          <file > myApp.log</file >          <encoder >              <pattern > %msg%n</pattern >          </encoder >      </appender >      <root >          <appender-ref  ref ="FILE" />      </root > </configuration > 
 
如果添加这个文件到资源目录下,会把日志写入myApp.log文件。
源码分析 从使用上来看。如果没有配置文件,框架会使用默认配置。有配置文件加载配置文件。根据提供的LoggerFactory类获取Logger,Logger调用方法打印日志。
LoggerFactory 看名字就是一个工厂类。又是一个入口类。这个类肯定会有默认配置和加配置文件的功能。生成Logger。
Logger是提供打印日志的方法。
加载配置文件源码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 Logger logger = LoggerFactory.getLogger(Test.class ); Logger logger = getLogger(clazz.getName()); ILoggerFactory iLoggerFactory = getILoggerFactory(); performInitialization(); bind(); staticLoggerBinderPathSet = findPossibleStaticLoggerBinderPathSet();  #这时会找到org/slf4j/impl/StaticLoggerBinder.class  StaticLoggerBinder.getSingleton(); SINGLETON.init ();new  ContextInitializer(defaultLoggerContext).autoConfig(); # 看到autoConfig了应该就到目标了。  URL url = findURLOfDefaultConfigurationFile(true );# 看系统参数logback.configurationFile 是否有设置  URL url = findConfigFileURLFromSystemProperties(myClassLoader, updateStatus);# logback.groovy 配置文件  url = getResource(GROOVY_AUTOCONFIG_FILE, myClassLoader, updateStatus);# logback-test.xml 配置文件  url = getResource(TEST_AUTOCONFIG_FILE, myClassLoader, updateStatus);# logback.xml 配置文件 return  getResource(AUTOCONFIG_FILE, myClassLoader, updateStatus); 最后url 是null 时说明没有配置文件 BasicConfigurator basicConfigurator = new  BasicConfigurator(); basicConfigurator.setContext(loggerContext); basicConfigurator.configure(loggerContext);#进入configure方法  这里配置了控制台输出的Appender、Encoder、Layout
 
这时就有Appender、Encoder、Layout要知道是啥
Appender是输出到哪去。
Encoder是输出的编码。
Layout是打印日志的格式。
Logger上下文 1 2 3 contextSelectorBinder.getContextSelector () return contextSelectorBinder.getContextSelector ().getLoggerContext (); ch.qos .logback .classic .LoggerContext 
 
Logger 1 2 3 4 5 return  iLoggerFactory.getLogger(name); LoggerContext类 childLogger = logger.createChildByName(childName); childLogger = new Logger(childName, this , this .loggerContext); loggerCache.put(childName, childLogger);
 
logger的结构为:  比如有一个com.test.a的类,这时会生成如下logger的父子结构
1 2 3 4 root 	com  		com .test 			com .test.a
 
打印日志源码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 logger.debug("Hello world." ); filterAndLog_0_Or3Plus(FQCN, null , Level.DEBUG, msg, null , null ); buildLoggingEventAndAppend(localFQCN, marker, level, msg, params , t); LoggingEvent le = new  LoggingEvent(localFQCN, this , level, msg, t, params ); callAppenders(le); writes += l.appendLoopOnAppenders(event );return  aai.appendLoopOnAppenders(event ); final Appender<E>[] appenderArray = appenderList.asTypedArray(); appenderArray[i].doAppend(e);# 这时会调用具体的Appender的实现类 this .append(eventObject); UnsynchronizedAppenderBase.doAppend(E eventObject) this .append(eventObject); OutputStreamAppender.subAppend(E event )lock .lock ();try  { 	writeOut(event ); } finally  { 	lock .unlock(); }this .encoder.doEncode(event ); String txt = layout.doLayout(event ); outputStream.write(convertToBytes(txt));if  (immediateFlush) 	outputStream.flush(); System.out .write(b);
 
这时发现consoleAppender使用ReentrantLock, system.out.write。
结构 Logger
1 ch.qos .logback .classic .Logger
 
Appender  在root的logger中AppenderAttachableImpl aai
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 Appender (ch . qos. logback. core) 	UnsynchronizedAppenderBase (ch . qos. logback. core) 		AsyncAppenderBase (ch . qos. logback. core) 			#异步写日志     	AsyncAppender (ch . qos. logback. classic)     OutputStreamAppender (ch . qos. logback. core)     	# 同步写控制台     	ConsoleAppender (ch . qos. logback. core)     	# 同步写文件     	FileAppender (ch . qos. logback. core)     		# 滚动同步写文件     		RollingFileAppender (ch . qos. logback. core. rolling)     DBAppenderBase (ch . qos. logback. core. db )     	DBAppender (ch . qos. logback. classic. db ) 	AppenderBase (ch . qos. logback. core)     NOPAppender (ch . qos. logback. core. helpers)     AbstractServerSocketAppender (ch . qos. logback. core. net. server)     	SSLServerSocketAppenderBase (ch . qos. logback. core. net. server)     		SSLServerSocketAppender (ch . qos. logback. classic. net. server)     	ServerSocketAppender (ch . qos. logback. classic. net. server)     JMSAppenderBase (ch . qos. logback. core. net)     	JMSTopicAppender (ch . qos. logback. classic. net)     	JMSQueueAppender (ch . qos. logback. classic. net)     SyslogAppenderBase (ch . qos. logback. core. net)     	SyslogAppender (ch . qos. logback. classic. net)     SMTPAppenderBase (ch . qos. logback. core. net)     	SMTPAppender (ch . qos. logback. classic. net)     SiftingAppenderBase (ch . qos. logback. core. sift)     	SiftingAppender (ch . qos. logback. classic. sift)     CyclicBufferAppender (ch . qos. logback. core. read)     ListAppender (ch . qos. logback. core. read)     AbstractSocketAppender (ch . qos. logback. core. net)     	AbstractSSLSocketAppender (ch . qos. logback. core. net)     		SSLSocketAppender (ch . qos. logback. classic. net)     	SocketAppender (ch . qos. logback. classic. net)
 
常用的 ConsoleAppender、FileAppender、RollingFileAppender、AsyncAppender
Encoder
1 2 3 4 5 6 7 8 9 10 Encoder (ch.qos.logback.core.encoder) 	EncoderBase (ch.qos.logback.core.encoder) 		# 输出不变只加换行符     EchoEncoder (ch.qos.logback.core.encoder)     # 布局包装     LayoutWrappingEncoder (ch.qos.logback.core.encoder)     	PatternLayoutEncoderBase (ch.qos.logback.core.pattern)     		# 图案布局     		PatternLayoutEncoder (ch.qos.logback.classic.encoder)     ObjectStreamEncoder (ch.qos.logback.core.encoder)
 
一般使用LayoutWrappingEncoder、PatternLayoutEncoder
Layout
1 2 3 4 5 6 7 8 9 10 11 12 13 Layout (ch.qos.logback.core)   LayoutBase (ch.qos.logback.core)   	# xml布局     XMLLayout (ch.qos.logback.classic.log4j)     # 固定格式的布局  %d{HH:mm:ss.SSS} [%thread]  %-5 level %logger{36 } - %msg%n     TTLLLayout (ch.qos.logback.classic.layout)     HTMLLayoutBase (ch.qos.logback.core.html)       # html 布局     	HTMLLayout (ch.qos.logback.classic.html)     EchoLayout (ch.qos.logback.core.layout)     PatternLayoutBase (ch.qos.logback.core.pattern)     	# 使用模式字符串配置的灵活布局。     	PatternLayout (ch.qos.logback.classic)
 
格式 1 2 3 4 5 6 7 8 <configuration >    多个appender   <appender > </appender >    多个logger   <logger > </logger >    一个root   <root > </root > </configuration > 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 <configuration >           <property  name ="log.path"  value ="/Users/qichuanhan/logs"  />           <property  name ="log.pattern"  value ="%d{HH:mm:ss.SSS} -[%X{traceId}]- [%thread] %-5level %logger{20} - [%method,%line] - %msg%n"  />           <appender  name ="console"  class ="ch.qos.logback.core.ConsoleAppender" >          <encoder >              <pattern > ${log.pattern}</pattern >          </encoder >      </appender >           <appender  name ="file_info"  class ="ch.qos.logback.core.rolling.RollingFileAppender" >          <file > ${log.path}/my-info.log</file >                   <rollingPolicy  class ="ch.qos.logback.core.rolling.TimeBasedRollingPolicy" >                           <fileNamePattern > ${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern >                           <maxHistory > 60</maxHistory >          </rollingPolicy >          <encoder >              <pattern > ${log.pattern}</pattern >          </encoder >          <filter  class ="ch.qos.logback.classic.filter.LevelFilter" >                           <level > INFO</level >                           <onMatch > ACCEPT</onMatch >                           <onMismatch > DENY</onMismatch >          </filter >      </appender >      <appender  name ="file_error"  class ="ch.qos.logback.core.rolling.RollingFileAppender" >          <file > ${log.path}/my-error.log</file >                   <rollingPolicy  class ="ch.qos.logback.core.rolling.TimeBasedRollingPolicy" >                           <fileNamePattern > ${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern >                           <maxHistory > 60</maxHistory >          </rollingPolicy >          <encoder >              <pattern > ${log.pattern}</pattern >          </encoder >          <filter  class ="ch.qos.logback.classic.filter.LevelFilter" >                           <level > ERROR</level >                           <onMatch > ACCEPT</onMatch >                           <onMismatch > DENY</onMismatch >          </filter >      </appender >      <root  level ="info" >          <appender-ref  ref ="console"  />          <appender-ref  ref ="file_info"  />          <appender-ref  ref ="file_error"  />      </root > </configuration > 
 
AsyncAppender 消费者:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 class  Worker  extends  Thread  {         public  void  run ()  {             AsyncAppenderBase<E> parent = AsyncAppenderBase.this ;             AppenderAttachableImpl<E> aai = parent.aai;                          while  (parent.isStarted()) {                 try  {                     E  e  =  parent.blockingQueue.take();                     aai.appendLoopOnAppenders(e);                 } catch  (InterruptedException ie) {                     break ;                 }             }             addInfo("Worker thread will flush remaining events before exiting. " );             for  (E e : parent.blockingQueue) {                 aai.appendLoopOnAppenders(e);                 parent.blockingQueue.remove(e);             }             aai.detachAndStopAllAppenders();         }     }
 
1 2 BlockingQueue<E> blockingQueue;public  static  final  int  DEFAULT_QUEUE_SIZE  =  256 ;
 
生产者:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 UnsynchronizedAppenderBase.doAppend(E eventObject);this .append(eventObject);@Override protected  void  append (E eventObject)  {   if  (isQueueBelowDiscardingThreshold() && isDiscardable(eventObject)) {     return ;   }   preprocess(eventObject);   put(eventObject); }private  void  put (E eventObject)  {   if  (neverBlock) {     blockingQueue.offer(eventObject);   } else  {     try  {       blockingQueue.put(eventObject);     } catch  (InterruptedException e) {                     Thread.currentThread().interrupt();     }   } }