Original address: http://kyfxbl.iteye.com/blog/1173788
Tomorrow to take a wife abroad to travel for a few days, so this period of time is not updated blog, before leaving before the last Post
In the previous article we talked about the logger class of the info () method through layer calls, and finally commissioned Appender to record the log, this blog we will continue to say, appender component is how to log
In fact Appender may be one of the most important components of the logback framework, although logger is the interface for logging, but if a logger is not associated with any appender, then this logger cannot log any information. In addition, although Logback provides many extensibility points, in applications, we may rarely extend the filter, and rarely extend layout and encoder, but our chances of expanding Appender are many
The old ritual, first of all, look at the big picture of Appender, here to show that the implementation of the Appender interface has 2 base classes, one is Appenderbase, the other is Unsynchronizedappenderbase, these 2 classes very close, 80 The code above is the same. If we're going to customize appender ourselves, just write a class that inherits from the 2 base classes.
First, there is a Appender interface, and then, as stated above, the Unsynchronizedappenderbase class implements this interface, but it is an abstract class itself, and it needs to inherit it to get the real implementation class. The Appender interface inherits the Filterattachable interface, and the Unsynchronizedappenderbase class holds a Filterattachableimpl class, Delegate this class to implement the method defined in the Filterattachable interface
Then Outputstreamappender is inherited from the Unsynchronizedappenderbase Appender implementation class, although it is not an abstract class, but the actual is not directly used, Its implementation class is the most common Consoleappender and Fileappender.
As long as you have used logback friends know, Appender element also need to configure encoder element, where the encoder interface is corresponding to this encoder element, because in fact, appender component is not the final actual log information components, It wants to delegate the encoder component to complete loggingevent formatting and logging
After describing the general structure, let's take a look at the Doappend () method from the Appender interface, which is how to finally record the log in a step-by-step manner.
The first is the Doappend () method inside the Unsynchronizedappenderbase, which mainly records the status state, then checks whether the filter on the Appender satisfies the filtering condition, and then calls the Appender () that implements the subclass. Method. It looks familiar, doesn't it? A design pattern-template method
Java code 
 
 
 - Public void Doappend (E eventobject) {
- //warning:the guard Check must is the first statement in the
- //Doappend () method. 
- //Prevent re-entry. 
- if (Boolean.TRUE.equals (Guard.get ())) {
- return; 
- }
- try {
- Guard.set (boolean.true);
- if (!  this.started) { 
- if (statusrepeatcount++ < allowed_repeats) {
- Addstatus (new Warnstatus (
- "attempted to append to non started appender [" + Name + "].", 
- this )); 
- }
- return; 
- }
- if (getfilterchaindecision (eventobject) = = Filterreply.deny) {
- return; 
- }
- //OK, we now invoke derived class ' implementation of append
- this.append (EventObject); 
- } catch (Exception e) {
- if (exceptioncount++ < allowed_repeats) {
- Adderror ("Appender [" + Name + "] failed to append.", e); 
- }
- } finally {
- Guard.set (Boolean.false);
- }
- }
- abstract protected void append (E eventobject); 
The above code is very simple, needless to say, we just look at the implementation of the class append () method is how to implement, here we choose Outputstreamappender Implementation class
Java code 
 
  
  - @Override
- protected void append (E eventobject) { 
- if (!isstarted ()) {
- return; 
- }
- Subappend (EventObject);
- }
First check whether this appender has been started, if not started directly back, if it has been started, then into a subappend () method
Java code 
 
 
 - /**
- * Actual writing occurs here.
- * <p>
- * Most subclasses of <code>WriterAppender</code> would need to override this
- * method.
- *
- * @since 0.9.0
- */
- protected void Subappend (E event) { 
- if (!isstarted ()) {
- return; 
- }
- try {
- //This step avoids LBCLASSIC-139
- if (event instanceof deferredprocessingaware) { 
- ((Deferredprocessingaware) event). Preparefordeferredprocessing ();
- }
- //The synchronization prevents the OutputStream from being closed while we
- //Is writing. It also prevents multiple thread from entering the same
- //Converter.  Converters assume that they is in a synchronized block. 
- synchronized (lock) {
- Writeout (event);
- }
- } catch (IOException IoE) {
- //As soon as an exception occurs, move to non-started state
- //And add a single errorstatus to the SM. 
- this.started = false; 
- Addstatus (new ErrorStatus ("IO failure in Appender", this , IoE)); 
- }
- }
This method actually does not do anything. After doing some checks, and then into the Writeout () method ...
Java code 
 
  
  - protected void Writeout (E event) throws IOException { 
- This.encoder.doEncode (event); 
- }
The Writeout () method delegate is configured to its encoder component to record
Java code 
 
  
  - Public void Doencode (E event) throws IOException { 
- String txt = layout.dolayout (event);
- Outputstream.write (converttobytes (TXT));
- Outputstream.flush ();
- }
Come here, finally finished. The encoder component also delegates its layout component to format the Loggingevent, returns a string, and then writes the formatted log information to the destination through the Outputstream.write () method.
Patience to see the friends here, may have been a bit dizzy, how appender need such trouble? What we're talking about here is just Consoleappender's doappend () whole process, not all appender are so complicated, and of course there are some more complex.
Here's a simple appender, which I wrote myself Myappender
Java code 
 
  
  -  public class myappender  EXTENDS&NBSP;APPENDERBASE<LOGGINGEVENT>&NBSP;{&NBSP;&NBSP;    
-     
-       @Override     
-      protected void  Append (Loggingevent eventobject)  {     
-           system.out.println (Eventobject.getmessage ());    
-      }    
-     
- }   
Well, very simple is not, if the Appender configuration to Logback.xml, then when the Logger.info () call, you will first walk into the Appenderbase class of Doappend () method, filter check and so on, Then enter the Myappender append () method, do not do other operations, directly to print the message to the console. Of course, because this class is extremely simplified, there is no encoder and layout, there is no way to control the output of the log time, there is no way to%thread such as the resolution processing. But this class can clearly express how the Appender component works: By invoking the filter chain by the Appenderbase class, and then by Appender implementing the class to delegate encoder parse Loggingevent, and then output to the destination
This is the end of the blog post here. So far, 5 blog posts have been:
1, first introduce how logback and slf4j docking
2, then introduce Logback's loggerfactory, that is, how Loggercontext was created
3, Next introduction loggerfactory how to create Logger
4. Then logger how to log, which involves cascading calls to Appender, and calling Turbofilter to filter the issue
5, this blog and the most common consoleappender as an example, introduced the Appender component how to output log information to the destination
The next blog topic has a variety of branches, you can talk about Dbappender and Fileappender is how to log, as this blog supplement, deepen understanding; You can continue to go further and talk about encoder and layout components , or go back and introduce how Logback was initialized.
When I accompany my wife to travel back, and then continue to update this series
Read Logback Source series article (v)--appender--Reprint