java中volatile关键字

java中volatile关键字的含义:http://www.cnblogs.com/aigongsi/archive/2012/04/01/2429166.html
Java transient关键字使用小记:http://www.cnblogs.com/lanxuezaipiao/p/3369962.html
Log4j的使用:http://donald-draper.iteye.com/admin/blogs/2332315
Log4j日志输出详解:http://donald-draper.iteye.com/admin/blogs/2332395
上一篇简单学习了Log4j的使用,今天来看一下,日志初始化,
我们就从下面这一句来看:
Java代码  收藏代码
private static Logger log = Logger.getLogger(testLog4j.class); 

查看Logger
Java代码  收藏代码
public class Logger extends Category 

    protected Logger(String name) 
    { 
        super(name); 
    } 
    //获取Logger 
    public static Logger getLogger(String name) 
    { 
        return LogManager.getLogger(name); 
    } 
    public static Logger getLogger(Class clazz) 
    { 
        return LogManager.getLogger(clazz.getName()); 
    } 
    static  
    { 
        FQCN = (org.apache.log4j.Logger.class).getName(); 
    } 
}  北京京东白条套现当面操作【电话/微信:135-2093-5605】/手续费低、积分POS机◆长期有效◆欢迎来电咨询

来看LogManager的getLogger方法
//LogManager
Java代码  收藏代码
public class LogManager 

public static Logger getLogger(String name) 
    { 
        return getLoggerRepository().getLogger(name); 
    } 
//获取本机LoggerRepository 
public static LoggerRepository getLoggerRepository() 
    { 
        if(repositorySelector == null) 
        { 
            repositorySelector = new DefaultRepositorySelector(new NOPLoggerRepository()); 
            guard = null; 
            Exception ex = new IllegalStateException("Class invariant violation"); 
            String msg = "log4j called after unloading, see http://logging.apache.org/log4j/1.2/faq.html#unload."; 
            if(isLikelySafeScenario(ex)) 
                LogLog.debug(msg, ex); 
            else 
                LogLog.error(msg, ex); 
        } 
        return repositorySelector.getLoggerRepository(); 
    } 
    public static final String DEFAULT_CONFIGURATION_FILE = "log4j.properties"; 
    static final String DEFAULT_XML_CONFIGURATION_FILE = "log4j.xml"; 
    public static final String DEFAULT_CONFIGURATION_KEY = "log4j.configuration"; 
    public static final String CONFIGURATOR_CLASS_KEY = "log4j.configuratorClass"; 
    public static final String DEFAULT_INIT_OVERRIDE_KEY = "log4j.defaultInitOverride"; 
    private static Object guard = null; 
    private static RepositorySelector repositorySelector; 
    //加载log4j配置文件,先加载log4j.xml,如果log4j.xml不存在, 
    //则加载log4j.properties文件 
    static  
    { 
        Hierarchy h = new Hierarchy(new RootLogger(Level.DEBUG)); 
        repositorySelector = new DefaultRepositorySelector(h); 
        String override = OptionConverter.getSystemProperty("log4j.defaultInitOverride", null); 
        if(override == null || "false".equalsIgnoreCase(override)) 
        { 
            String configurationOptionStr = OptionConverter.getSystemProperty("log4j.configuration", null); 
            String configuratorClassName = OptionConverter.getSystemProperty("log4j.configuratorClass", null); 
            URL url = null; 
            if(configurationOptionStr == null) 
            { 
                url = Loader.getResource("log4j.xml"); 
                if(url == null) 
                    url = Loader.getResource("log4j.properties"); 
            } else 
            { 
                try 
                { 
                    url = new URL(configurationOptionStr); 
                } 
                catch(MalformedURLException ex) 
                { 
                    url = Loader.getResource(configurationOptionStr); 
                } 
            } 
            if(url != null) 
            { 
                LogLog.debug("Using URL [" + url + "] for automatic log4j configuration."); 
                try 
                { 
                    OptionConverter.selectAndConfigure(url, configuratorClassName, getLoggerRepository()); 
                } 
       } 
    } 
    } 


Java代码  收藏代码
//DefaultRepositorySelector 
public class DefaultRepositorySelector 
    implements RepositorySelector 

    public DefaultRepositorySelector(LoggerRepository repository) 
    { 
        this.repository = repository; 
    } 
    public LoggerRepository getLoggerRepository() 
    { 
        return repository; 
    } 
    final LoggerRepository repository; 

http://bjxinyongka.webnode.com/
http://cyxykdh.webnode.com/
http://haidian.webnode.com/
http://shunyi4.webnode.com/
http://tongzhou.webnode.com/
http://fengtai.webnode.com/
http://daxing.webnode.com/
http://changping0.webnode.com/
http://sjsxykdh.webnode.com/
http://tiantong.webnode.com/
http://huilongg.webnode.com/
http://guomao6.webnode.com/
http://shuangj.webnode.com/
http://visatx.webnode.com/
http://bjdhxyk.webnode.com/
//NOPLoggerRepository
Java代码  收藏代码
public final class NOPLoggerRepository 
    implements LoggerRepository 

    //从这里看,Logger实际上为NOPLogger 
      public Logger getLogger(String name) 
    { 
        return new NOPLogger(this, name); 
    } 


//NOPLogger
Java代码  收藏代码
public final class NOPLogger extends Logger 

 
    public NOPLogger(NOPLoggerRepository repo, String name) 
    { 
        super(name); 
        repository = repo; 
        level = Level.OFF; 
        parent = this; 
    } 


而Logger继承Category
Java代码  收藏代码
public class Logger extends Category 

 
    protected Logger(String name) 
    { 
        super(name); 
    } 


//Category
Java代码  收藏代码
public class Category 
    implements AppenderAttachable 

 
    protected Category(String name) 
    { 
        additive = true; 
        this.name = name; 
    } 
    protected String name; 
    //volatile 
    protected volatile Level level; 
    protected volatile Category parent; 
    private static final String FQCN; 
    protected ResourceBundle resourceBundle; 
    protected LoggerRepository repository; 
    AppenderAttachableImpl aai; 
    protected boolean additive; 
 
    static  
    { 
        FQCN = (org.apache.log4j.Category.class).getName(); 
    } 


//Level
Java代码  收藏代码
public class Level extends Priority 
    implements Serializable 

      protected Level(int level, String levelStr, int syslogEquivalent) 
    { 
        super(level, levelStr, syslogEquivalent); 
    } 
    public static final int TRACE_INT = 5000; 
    public static final Level OFF = new Level(2147483647, "OFF", 0); 
    public static final Level FATAL = new Level(50000, "FATAL", 0); 
    public static final Level ERROR = new Level(40000, "ERROR", 3); 
    public static final Level WARN = new Level(30000, "WARN", 4); 
    public static final Level INFO = new Level(20000, "INFO", 6); 
    public static final Level DEBUG = new Level(10000, "DEBUG", 7); 
    public static final Level TRACE = new Level(5000, "TRACE", 7); 
    public static final Level ALL = new Level(-2147483648, "ALL", 7); 
    static final long serialVersionUID = 3491141966387921974L; 


//Priority
Java代码  收藏代码
public class Priority 

 
    protected Priority() 
    { 
        level = 10000; 
        levelStr = "DEBUG"; 
        syslogEquivalent = 7; 
    } 
 
    protected Priority(int level, String levelStr, int syslogEquivalent) 
    { 
        this.level = level; 
        this.levelStr = levelStr; 
        this.syslogEquivalent = syslogEquivalent; 
    } 
    //比较日志级别 
      public boolean isGreaterOrEqual(Priority r) 
    { 
        return level >= r.level; 
    } 
    transient int level; 
    transient String levelStr; 
    transient int syslogEquivalent; 
    public static final int OFF_INT = 2147483647; 
    public static final int FATAL_INT = 50000; 
    public static final int ERROR_INT = 40000; 
    public static final int WARN_INT = 30000; 
    public static final int INFO_INT = 20000; 
    public static final int DEBUG_INT = 10000; 
    public static final int ALL_INT = -2147483648; 
    public static final Priority FATAL = new Level(50000, "FATAL", 0); 
    public static final Priority ERROR = new Level(40000, "ERROR", 3); 
    public static final Priority WARN = new Level(30000, "WARN", 4); 
    public static final Priority INFO = new Level(20000, "INFO", 6); 
    public static final Priority DEBUG = new Level(10000, "DEBUG", 7); 


我们在回到LogManager加载log4j属性文件,关键在这一句
Java代码  收藏代码
OptionConverter.selectAndConfigure(url, configuratorClassName, getLoggerRepository()); 

这个LoggerRepository实际为NOPLoggerRepository
Java代码  收藏代码
public class OptionConverter 

public static void selectAndConfigure(URL url, String clazz, LoggerRepository hierarchy) 
    { 
        Configurator configurator = null; 
        String filename = url.getFile(); 
        if(clazz == null && filename != null && filename.endsWith(".xml")) 
            clazz = "org.apache.log4j.xml.DOMConfigurator"; 
    //XML配置解析 
        if(clazz != null) 
        { 
            LogLog.debug("Preferred configurator class: " + clazz); 
            configurator = (Configurator)instantiateByClassName(clazz, org.apache.log4j.spi.Configurator.class, null); 
            
        } else 
        { 
        //java属性文件解析log4j.properties 
            configurator = new PropertyConfigurator(); 
        } 
    //配置NOPLoggerRepository 
        configurator.doConfigure(url, hierarchy); 
    } 
    static String DELIM_START = "${"; 
    static char DELIM_STOP = '}'; 
    static int DELIM_START_LEN = 2; 
    static int DELIM_STOP_LEN = 1; 
 
  } 


来看log4j.properties属性文件解析
//PropertyConfigurator
Java代码  收藏代码
public class PropertyConfigurator 
    implements Configurator 

    protected Hashtable registry; 
    private LoggerRepository repository; 
    protected LoggerFactory loggerFactory; 
    static final String CATEGORY_PREFIX = "log4j.category."; 
    static final String LOGGER_PREFIX = "log4j.logger."; 
    static final String FACTORY_PREFIX = "log4j.factory"; 
    static final String ADDITIVITY_PREFIX = "log4j.additivity."; 
    static final String ROOT_CATEGORY_PREFIX = "log4j.rootCategory"; 
    static final String ROOT_LOGGER_PREFIX = "log4j.rootLogger"; 
    static final String APPENDER_PREFIX = "log4j.appender."; 
    static final String RENDERER_PREFIX = "log4j.renderer."; 
    static final String THRESHOLD_PREFIX = "log4j.threshold"; 
    private static final String THROWABLE_RENDERER_PREFIX = "log4j.throwableRenderer"; 
    private static final String LOGGER_REF = "logger-ref"; 
    private static final String ROOT_REF = "root-ref"; 
    private static final String APPENDER_REF_TAG = "appender-ref"; 
    public static final String LOGGER_FACTORY_KEY = "log4j.loggerFactory"; 
    private static final String RESET_KEY = "log4j.reset"; 
    private static final String INTERNAL_ROOT_NAME = "root"; 
 
    public PropertyConfigurator() 
    { 
        registry = new Hashtable(11); 
        loggerFactory = new DefaultCategoryFactory(); 
    } 
    //加载URL文件到Properties 
    public void doConfigure(URL configURL, LoggerRepository hierarchy) 
    { 
        Properties props; 
        InputStream istream; 
        props = new Properties(); 
        istream = null; 
        URLConnection uConn = null; 
        URLConnection uConn = configURL.openConnection(); 
        uConn.setUseCaches(false); 
        istream = uConn.getInputStream(); 
        props.load(istream); 
    //加载URL文件到Properties 
        doConfigure(props, hierarchy); 
    } 
    //根据properties文件配置NOPLoggerRepository 
    public void doConfigure(Properties properties, LoggerRepository hierarchy) 
    { 
        repository = hierarchy; 
        String value = properties.getProperty("log4j.debug"); 
        if(value == null) 
        { 
            value = properties.getProperty("log4j.configDebug"); 
            if(value != null) 
                LogLog.warn("[log4j.configDebug] is deprecated. Use [log4j.debug] instead."); 
        } 
        if(value != null) 
            LogLog.setInternalDebugging(OptionConverter.toBoolean(value, true)); 
        String reset = properties.getProperty("log4j.reset"); 
        if(reset != null && OptionConverter.toBoolean(reset, false)) 
            hierarchy.resetConfiguration(); 
        String thresholdStr = OptionConverter.findAndSubst("log4j.threshold", properties); 
        if(thresholdStr != null) 
        { 
            hierarchy.setThreshold(OptionConverter.toLevel(thresholdStr, Level.ALL)); 
            LogLog.debug("Hierarchy threshold set to [" + hierarchy.getThreshold() + "]."); 
        } 
    //配置RootCategory,rootLogger,appenders 
        configureRootCategory(properties, hierarchy); 
        configureLoggerFactory(properties); 
        parseCatsAndRenderers(properties, hierarchy); 
        LogLog.debug("Finished configuring."); 
        registry.clear(); 
    } 


//配置RootCategory,rootLogger,appenders
Java代码  收藏代码
void configureRootCategory(Properties props, LoggerRepository hierarchy) 
    { 
        String effectiveFrefix = "log4j.rootLogger"; 
        String value = OptionConverter.findAndSubst("log4j.rootLogger", props); 
    if(value == null) 
        { 
            LogLog.debug("Could not find root logger information. Is this OK?"); 
        } else 
        { 
            Logger root = hierarchy.getRootLogger(); 
            synchronized(root) 
            { 
                parseCategory(props, root, effectiveFrefix, "root", value); 
            } 
        } 
    } 

来看 OptionConverter.findAndSubst
//返回key对应的属性
Java代码  收藏代码
public static String findAndSubst(String key, Properties props) 
    { 
        String value; 
        value = props.getProperty(key); 


//NOPLoggerRepository,获取rootLogger
Java代码  收藏代码
public Logger getRootLogger() 
   { 
       return new NOPLogger(this, "root"); 
   } 

//PropertyConfigurator
Java代码  收藏代码
void parseCategory(Properties props, Logger logger, String optionKey, String loggerName, String value) 
    { 
        StringTokenizer st = new StringTokenizer(value, ","); 
        if(!value.startsWith(",") && !value.equals("")) 
        { 
            if(!st.hasMoreTokens()) 
                return; 
            //获取rootLogger,日志级别 
            String levelStr = st.nextToken(); 
            if("inherited".equalsIgnoreCase(levelStr) || "null".equalsIgnoreCase(levelStr)) 
            { 
                if(loggerName.equals("root")) 
                    LogLog.warn("The root logger cannot be set to null."); 
                else 
                    logger.setLevel(null); 
            } else 
            { 
                //设置rootLogger,日志级别 
                logger.setLevel(OptionConverter.toLevel(levelStr, Level.DEBUG)); 
            } 
            LogLog.debug("Category " + loggerName + " set to " + logger.getLevel()); 
        } 
    //移除Appenders 
        logger.removeAllAppenders(); 
        do 
        { 
            if(!st.hasMoreTokens()) 
                break; 
            String appenderName = st.nextToken().trim(); 
            if(appenderName != null && !appenderName.equals(",")) 
            { 
                LogLog.debug("Parsing appender named \"" + appenderName + "\"."); 
        //根据appenderName解析Appender 
                Appender appender = parseAppender(props, appenderName); 
                if(appender != null) 
            //添加appender 
                    logger.addAppender(appender); 
            } 
        } while(true); 
    } 

//根据appenderName解析Appender
Java代码  收藏代码
Appender parseAppender(Properties props, String appenderName) 
    { 
        Appender appender = registryGet(appenderName); 
        if(appender != null) 
        { 
            LogLog.debug("Appender \"" + appenderName + "\" was already parsed."); 
            return appender; 
        } 
    //log4j.appender的前缀 
        String prefix = "log4j.appender." + appenderName; 
        //log4j.appender.appenderName.layout 
        String layoutPrefix = prefix + ".layout"; 
    //加载Appender,Class, 
    //log4j.appender.D = org.apache.log4j.DailyRollingFileAppender 
        appender = (Appender)OptionConverter.instantiateByKey(props, prefix, org.apache.log4j.Appender.class, null); 
        appender.setName(appenderName); 
        if(appender instanceof OptionHandler) 
        { 
            if(appender.requiresLayout()) 
            { 
            //加载Layout,class, 
        //log4j.appender.D.layout = org.apache.log4j.PatternLayout 
                Layout layout = (Layout)OptionConverter.instantiateByKey(props, layoutPrefix, org.apache.log4j.Layout.class, null); 
                if(layout != null) 
                { 
                    appender.setLayout(layout); 
                    LogLog.debug("Parsing layout options for \"" + appenderName + "\"."); 
            //设置layout的属性 
                    PropertySetter.setProperties(layout, props, layoutPrefix + "."); 
                    LogLog.debug("End of parsing for \"" + appenderName + "\"."); 
                } 
            } 
            String errorHandlerPrefix = prefix + ".errorhandler"; 
            String errorHandlerClass = OptionConverter.findAndSubst(errorHandlerPrefix, props); 
            if(errorHandlerClass != null) 
            { 
                ErrorHandler eh = (ErrorHandler)OptionConverter.instantiateByKey(props, errorHandlerPrefix, org.apache.log4j.spi.ErrorHandler.class, null); 
                if(eh != null) 
                { 
                    appender.setErrorHandler(eh); 
                    LogLog.debug("Parsing errorhandler options for \"" + appenderName + "\"."); 
                    parseErrorHandler(eh, errorHandlerPrefix, props, repository); 
                    Properties edited = new Properties(); 
                    String keys[] = { 
                        errorHandlerPrefix + "." + "root-ref", errorHandlerPrefix + "." + "logger-ref", errorHandlerPrefix + "." + "appender-ref" 
                    }; 
                    Iterator iter = props.entrySet().iterator(); 
                    do 
                    { 
                        if(!iter.hasNext()) 
                            break; 
                        java.util.Map.Entry entry = (java.util.Map.Entry)iter.next(); 
                        int i; 
                        for(i = 0; i < keys.length && !keys[i].equals(entry.getKey()); i++); 
                        if(i == keys.length) 
                            edited.put(entry.getKey(), entry.getValue()); 
                    } while(true); 
                    PropertySetter.setProperties(eh, edited, errorHandlerPrefix + "."); 
                    LogLog.debug("End of errorhandler parsing for \"" + appenderName + "\"."); 
                } 
            } 
        //设置Appender属性 
            PropertySetter.setProperties(appender, props, prefix + "."); 
            LogLog.debug("Parsed \"" + appenderName + "\" options."); 
        } 
        parseAppenderFilters(props, appenderName, appender); 
        //将Appender放入registry 
        registryPut(appender); 
        return appender; 
    } 

//OptionConverter.instantiateByKey
Java代码  收藏代码
public static Object instantiateByKey(Properties props, String key, Class superClass, Object defaultValue) 
    { 
        String className = findAndSubst(key, props); 
        if(className == null) 
        { 
            LogLog.error("Could not find value for key " + key); 
            return defaultValue; 
        } else 
        { 
            return instantiateByClassName(className.trim(), superClass, defaultValue); 
        } 
    } 

//PropertyConfigurator
// protected Hashtable registry;HashTable<String,Appender>
//将Appender放入registry
Java代码  收藏代码
void registryPut(Appender appender) 
    { 
        registry.put(appender.getName(), appender); 
    } 

下面我们来看看logger.addAppender,都做了些什么
Java代码  收藏代码
public class Category 
    implements AppenderAttachable 

//添加Appender 
    public synchronized void addAppender(Appender newAppender) 
    { 
        if(aai == null) 
            aai = new AppenderAttachableImpl(); 
        aai.addAppender(newAppender); 
    //通知repository,添加Appender事件 
        repository.fireAddAppenderEvent(this, newAppender); 
    } 
    //移除AllAppenders 
public synchronized void removeAllAppenders() 
    { 
        if(aai != null) 
        { 
            Vector appenders = new Vector(); 
            for(Enumeration iter = aai.getAllAppenders(); iter != null && iter.hasMoreElements(); appenders.add(iter.nextElement())); 
            aai.removeAllAppenders(); 
            for(Enumeration iter = appenders.elements(); iter.hasMoreElements(); fireRemoveAppenderEvent((Appender)iter.nextElement())); 
            aai = null; 
        } 
    } 
    


//AppenderAttachableImpl
Java代码  收藏代码
public class AppenderAttachableImpl 
    implements AppenderAttachable 

//添加Appender 
public void addAppender(Appender newAppender) 
    { 
        if(newAppender == null) 
            return; 
        if(appenderList == null) 
            appenderList = new Vector(1); 
        if(!appenderList.contains(newAppender)) 
            appenderList.addElement(newAppender); 
    } 
    //Vector<Appender> 
     protected Vector appenderList; 


总结:
从以上我们可以看出:log4j,通过LogManager的static语句块,加载配置log4j.properties,由OptionConverter去加载log4j.properties,并委托给PropertyConfigurator,去配置RootLogger,根据RootLogger获取Appender,然后根据属性文件初始化Appender,并添加到RootLogger的appender集合中。

猜你喜欢

转载自a61651817jiweixia.iteye.com/blog/2332425