美文网首页
log4j2-core的源码学习(一)

log4j2-core的源码学习(一)

作者: 天草二十六_简村人 | 来源:发表于2019-09-26 10:10 被阅读0次

    一、概述
    log4j2作为一个高性能的日志组件,里面有许多值得学习借鉴的地方。本文是抛砖引玉,先对某一个类的写法进行分析。

    二、EventRoute枚举类

    package org.apache.logging.log4j.core.async;
    
    import org.apache.logging.log4j.Level;
    import org.apache.logging.log4j.Marker;
    import org.apache.logging.log4j.core.LogEvent;
    import org.apache.logging.log4j.core.appender.AsyncAppender;
    import org.apache.logging.log4j.message.Message;
    
    public enum EventRoute {
        ENQUEUE {
            public void logMessage(AsyncLogger asyncLogger, String fqcn, Level level, Marker marker, Message message, Throwable thrown) {
            }
    
            public void logMessage(AsyncLoggerConfig asyncLoggerConfig, LogEvent event) {
                asyncLoggerConfig.callAppendersInBackgroundThread(event);
            }
    
            public void logMessage(AsyncAppender asyncAppender, LogEvent logEvent) {
                asyncAppender.logMessageInBackgroundThread(logEvent);
            }
        },
        SYNCHRONOUS {
            public void logMessage(AsyncLogger asyncLogger, String fqcn, Level level, Marker marker, Message message, Throwable thrown) {
            }
    
            public void logMessage(AsyncLoggerConfig asyncLoggerConfig, LogEvent event) {
                asyncLoggerConfig.callAppendersInCurrentThread(event);
            }
    
            public void logMessage(AsyncAppender asyncAppender, LogEvent logEvent) {
                asyncAppender.logMessageInCurrentThread(logEvent);
            }
        },
        DISCARD {
            public void logMessage(AsyncLogger asyncLogger, String fqcn, Level level, Marker marker, Message message, Throwable thrown) {
            }
    
            public void logMessage(AsyncLoggerConfig asyncLoggerConfig, LogEvent event) {
            }
    
            public void logMessage(AsyncAppender asyncAppender, LogEvent coreEvent) {
            }
        };
    
        private EventRoute() {
        }
    
        public abstract void logMessage(AsyncLogger var1, String var2, Level var3, Marker var4, Message var5, Throwable var6);
    
        public abstract void logMessage(AsyncLoggerConfig var1, LogEvent var2);
    
        public abstract void logMessage(AsyncAppender var1, LogEvent var2);
    }
    
    

    1、第一,枚举定义了一个私有构造方法,意味着不对外new。
    2、第二,声明了三个抽象方法,枚举作为一个语法糖,有必要针对上面的枚举类,查看它的字节码。详细见下文。
    3、第三,定义了三个成员变量,内部实现不一样。
    4、总结,其实这里就是通过枚举做到了单例的设计模式。

    三、EventRoute枚举类的字节码

    // class version 51.0 (51)
    // access flags 0x4421
    // signature Ljava/lang/Enum<Lorg/apache/logging/log4j/core/async/EventRoute;>;
    // declaration: org/apache/logging/log4j/core/async/EventRoute extends java.lang.Enum<org.apache.logging.log4j.core.async.EventRoute>
    public abstract enum org/apache/logging/log4j/core/async/EventRoute extends java/lang/Enum  {
    
      // compiled from: EventRoute.java
      // access flags 0x4008
      static enum INNERCLASS org/apache/logging/log4j/core/async/EventRoute$3 null null
      // access flags 0x4008
      static enum INNERCLASS org/apache/logging/log4j/core/async/EventRoute$2 null null
      // access flags 0x4008
      static enum INNERCLASS org/apache/logging/log4j/core/async/EventRoute$1 null null
    
      // access flags 0x4019
      public final static enum Lorg/apache/logging/log4j/core/async/EventRoute; ENQUEUE
    
      // access flags 0x4019
      public final static enum Lorg/apache/logging/log4j/core/async/EventRoute; SYNCHRONOUS
    
      // access flags 0x4019
      public final static enum Lorg/apache/logging/log4j/core/async/EventRoute; DISCARD
    
      // access flags 0x101A
      private final static synthetic [Lorg/apache/logging/log4j/core/async/EventRoute; $VALUES
    
      // access flags 0x9
      public static values()[Lorg/apache/logging/log4j/core/async/EventRoute;
       L0
        LINENUMBER 34 L0
        GETSTATIC org/apache/logging/log4j/core/async/EventRoute.$VALUES : [Lorg/apache/logging/log4j/core/async/EventRoute;
        INVOKEVIRTUAL [Lorg/apache/logging/log4j/core/async/EventRoute;.clone ()Ljava/lang/Object;
        CHECKCAST [Lorg/apache/logging/log4j/core/async/EventRoute;
        ARETURN
        MAXSTACK = 1
        MAXLOCALS = 0
    
      // access flags 0x9
      public static valueOf(Ljava/lang/String;)Lorg/apache/logging/log4j/core/async/EventRoute;
       L0
        LINENUMBER 34 L0
        LDC Lorg/apache/logging/log4j/core/async/EventRoute;.class
        ALOAD 0
        INVOKESTATIC java/lang/Enum.valueOf (Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum;
        CHECKCAST org/apache/logging/log4j/core/async/EventRoute
        ARETURN
       L1
        LOCALVARIABLE name Ljava/lang/String; L0 L1 0
        MAXSTACK = 2
        MAXLOCALS = 1
    
      // access flags 0x2
      // signature ()V
      // declaration: void <init>()
      private <init>(Ljava/lang/String;I)V
       L0
        LINENUMBER 34 L0
        ALOAD 0
        ALOAD 1
        ILOAD 2
        INVOKESPECIAL java/lang/Enum.<init> (Ljava/lang/String;I)V
        RETURN
       L1
        LOCALVARIABLE this Lorg/apache/logging/log4j/core/async/EventRoute; L0 L1 0
        MAXSTACK = 3
        MAXLOCALS = 3
    
      // access flags 0x401
      public abstract logMessage(Lorg/apache/logging/log4j/core/async/AsyncLogger;Ljava/lang/String;Lorg/apache/logging/log4j/Level;Lorg/apache/logging/log4j/Marker;Lorg/apache/logging/log4j/message/Message;Ljava/lang/Throwable;)V
    
      // access flags 0x401
      public abstract logMessage(Lorg/apache/logging/log4j/core/async/AsyncLoggerConfig;Lorg/apache/logging/log4j/core/LogEvent;)V
    
      // access flags 0x401
      public abstract logMessage(Lorg/apache/logging/log4j/core/appender/AsyncAppender;Lorg/apache/logging/log4j/core/LogEvent;)V
    
      // access flags 0x1000
      synthetic <init>(Ljava/lang/String;ILorg/apache/logging/log4j/core/async/EventRoute$1;)V
       L0
        LINENUMBER 34 L0
        ALOAD 0
        ALOAD 1
        ILOAD 2
        INVOKESPECIAL org/apache/logging/log4j/core/async/EventRoute.<init> (Ljava/lang/String;I)V
        RETURN
       L1
        LOCALVARIABLE this Lorg/apache/logging/log4j/core/async/EventRoute; L0 L1 0
        LOCALVARIABLE x0 Ljava/lang/String; L0 L1 1
        LOCALVARIABLE x1 I L0 L1 2
        LOCALVARIABLE x2 Lorg/apache/logging/log4j/core/async/EventRoute$1; L0 L1 3
        MAXSTACK = 3
        MAXLOCALS = 4
    
      // access flags 0x8
      static <clinit>()V
       L0
        LINENUMBER 38 L0
        NEW org/apache/logging/log4j/core/async/EventRoute$1
        DUP
        LDC "ENQUEUE"
        ICONST_0
        INVOKESPECIAL org/apache/logging/log4j/core/async/EventRoute$1.<init> (Ljava/lang/String;I)V
        PUTSTATIC org/apache/logging/log4j/core/async/EventRoute.ENQUEUE : Lorg/apache/logging/log4j/core/async/EventRoute;
       L1
        LINENUMBER 57 L1
        NEW org/apache/logging/log4j/core/async/EventRoute$2
        DUP
        LDC "SYNCHRONOUS"
        ICONST_1
        INVOKESPECIAL org/apache/logging/log4j/core/async/EventRoute$2.<init> (Ljava/lang/String;I)V
        PUTSTATIC org/apache/logging/log4j/core/async/EventRoute.SYNCHRONOUS : Lorg/apache/logging/log4j/core/async/EventRoute;
       L2
        LINENUMBER 76 L2
        NEW org/apache/logging/log4j/core/async/EventRoute$3
        DUP
        LDC "DISCARD"
        ICONST_2
        INVOKESPECIAL org/apache/logging/log4j/core/async/EventRoute$3.<init> (Ljava/lang/String;I)V
        PUTSTATIC org/apache/logging/log4j/core/async/EventRoute.DISCARD : Lorg/apache/logging/log4j/core/async/EventRoute;
       L3
        LINENUMBER 34 L3
        ICONST_3
        ANEWARRAY org/apache/logging/log4j/core/async/EventRoute
        DUP
        ICONST_0
        GETSTATIC org/apache/logging/log4j/core/async/EventRoute.ENQUEUE : Lorg/apache/logging/log4j/core/async/EventRoute;
        AASTORE
        DUP
        ICONST_1
        GETSTATIC org/apache/logging/log4j/core/async/EventRoute.SYNCHRONOUS : Lorg/apache/logging/log4j/core/async/EventRoute;
        AASTORE
        DUP
        ICONST_2
        GETSTATIC org/apache/logging/log4j/core/async/EventRoute.DISCARD : Lorg/apache/logging/log4j/core/async/EventRoute;
        AASTORE
        PUTSTATIC org/apache/logging/log4j/core/async/EventRoute.$VALUES : [Lorg/apache/logging/log4j/core/async/EventRoute;
        RETURN
        MAXSTACK = 4
        MAXLOCALS = 0
    }
    
    

    分析上述的字节码内容,可以得知以下信息:
    1、它继承了java.lang.Enum,详细的jdk源码见下文。
    2、包含静态方法,values()和valueOf();定义了三个静态不可变的成员变量ENQUEUE、SYNCHRONOUS、DISCARD。
    特别是values()方法,在父类Enum.java中也未能找到。

    五、java.lang.Enum.java的源码

    //
    // Source code recreated from a .class file by IntelliJ IDEA
    // (powered by Fernflower decompiler)
    //
    
    package java.lang;
    
    import java.io.IOException;
    import java.io.InvalidObjectException;
    import java.io.ObjectInputStream;
    import java.io.ObjectStreamException;
    import java.io.Serializable;
    
    public abstract class Enum<E extends Enum<E>> implements Comparable<E>, Serializable {
        private final String name;
        private final int ordinal;
    
        public final String name() {
            return this.name;
        }
    
        public final int ordinal() {
            return this.ordinal;
        }
    
        protected Enum(String var1, int var2) {
            this.name = var1;
            this.ordinal = var2;
        }
    
        public String toString() {
            return this.name;
        }
    
        public final boolean equals(Object var1) {
            return this == var1;
        }
    
        public final int hashCode() {
            return super.hashCode();
        }
    
        protected final Object clone() throws CloneNotSupportedException {
            throw new CloneNotSupportedException();
        }
    
        public final int compareTo(E var1) {
            if (this.getClass() != var1.getClass() && this.getDeclaringClass() != var1.getDeclaringClass()) {
                throw new ClassCastException();
            } else {
                return this.ordinal - var1.ordinal;
            }
        }
    
        public final Class<E> getDeclaringClass() {
            Class var1 = this.getClass();
            Class var2 = var1.getSuperclass();
            return var2 == Enum.class ? var1 : var2;
        }
    
        public static <T extends Enum<T>> T valueOf(Class<T> var0, String var1) {
            Enum var2 = (Enum)var0.enumConstantDirectory().get(var1);
            if (var2 != null) {
                return var2;
            } else if (var1 == null) {
                throw new NullPointerException("Name is null");
            } else {
                throw new IllegalArgumentException("No enum constant " + var0.getCanonicalName() + "." + var1);
            }
        }
    
        protected final void finalize() {
        }
    
        private void readObject(ObjectInputStream var1) throws IOException, ClassNotFoundException {
            throw new InvalidObjectException("can't deserialize enum");
        }
    
        private void readObjectNoData() throws ObjectStreamException {
            throw new InvalidObjectException("can't deserialize enum");
        }
    }
    

    1、枚举类最重要的一个点就是它的成员变量和大多数方法,都是有final修饰,为不可变的。
    做到了线程安全。
    2、它实现了Serializable接口,主动抛异常InvalidObjectException,“can't deserialize enum"。
    3、实现了接口Comparable,compareTo()方法实现,当类相同,且都是枚举,比较他们的ordinal大小。
    3、valueOf(),实际上还是依靠values()方法,把成员变量放到一个hashmap里。
    4、像equals/hashCode/clone/compareTo/都是final方法。
    equals方法实现,就是 == 比较。

    六、总结
    一个小小的类,50来行代码,包含的知识点,有单例模式、语法糖--枚举。

    相关文章

      网友评论

          本文标题:log4j2-core的源码学习(一)

          本文链接:https://www.haomeiwen.com/subject/pjzwyctx.html