log4j几个tips

log4j是很常用的日志框架,这里总结几个小知识点:

1. logger是以名称为key,logger为value的形式存储在Hashtable里,所以,logger作为入参不需要传入引用,直接输入名称get即可。

LogFactoryImpl.java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

/**

* The {@link org.apache.commons.logging.Log} instances that have

* already been created, keyed by logger name.

*/

protected Hashtable instances = new Hashtable();

public Log getInstance(String name) throws LogConfigurationException {

Log instance = (Log) instances.get(name);

if (instance == null) {

instance = newInstance(name);

instances.put(name, instance);

}

return (instance);

}

2. logger的继承关系是根据名称的“.”分割来区分,表现为子logger打印日志时遍历父logger里的appender的进行日志打印。

Category.java

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

public

void callAppenders(LoggingEvent event) {

int writes = 0;

for(Category c = this; c != null; c=c.parent) {

// Protected against simultaneous call to addAppender, removeAppender,...

synchronized(c) {

if(c.aai != null) {

writes += c.aai.appendLoopOnAppenders(event);

}

if(!c.additive) {

break;

}

}

}

if(writes == 0) {

repository.emitNoAppenderWarning(this);

}

}

3.定义模块名为常量,按模块名称取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

31

32

33

34

35

36

37

38

39

40

41

42

43

package com.zoo;

import java.util.Properties;

import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

import org.apache.log4j.PropertyConfigurator;

/**

*

* @author yankai913@gmail.com

* @date 2014年12月22日

*/

public class LogTest {

static final Log log = LogFactory.getLog(LogTest.class);

public static void main(String[] args) {

Properties properties = new Properties();

properties.setProperty("log4j.rootLogger", "DEBUG,stdout");

properties.setProperty("log4j.appender.stdout", "org.apache.log4j.ConsoleAppender");

properties.setProperty("log4j.appender.stdout.layout", "org.apache.log4j.PatternLayout");

properties.setProperty("log4j.appender.stdout.layout.ConversionPattern",

"%d [%t] %-5p %C{6} (%F:%L) - %m%n");

// log4j的继承关系是"."

// log --> com.zoo.LogTest

// log2(父log) --> com.zoo

// log3(父log2) --> com

// 以此类推

// 子logger的继承关系表现是,子logger打印日志时,遍历父logger里的appender

// 进行日志打印,"com.zoo.LogTest"的父子logger分别是:

// "com.zoo.LogTest"的logger -> "com.zoo"的logger -> "root"的logger。

// 以下这句话定义了上述的log2(即父log),导致日志打印2次。

properties.setProperty("log4j.logger.com.zoo", "INFO, stdout");

// 以下这句话定义com.zoo包的logger(即log2)的appender不被继承,日志打印只有一条。

properties.setProperty("log4j.additivity.com.zoo", "false");

PropertyConfigurator.configure(properties);

System.out.println(log);

log.info("Hello World!");

System.out.println("end");

}

}

示例二

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

66

67

68

69

70

71

72

73

74

75

76

77

78

package com.zoo;

import java.util.Properties;

import org.apache.commons.logging.Log;

import org.apache.commons.logging.LogFactory;

import org.apache.log4j.PropertyConfigurator;

/**

*

* @author yankai913@gmail.com

* @date 2014年12月22日

*/

public class LogTest2 {

// 定义公共的logerName,按module分

static final String Module1_LogName = "Module1";

static final String Module2_LogName = "Module2";

public static void main(String[] args) {

Properties properties = new Properties();

properties.setProperty("log4j.rootLogger", "DEBUG,file");

properties.setProperty("log4j.appender.file", "org.apache.log4j.FileAppender");

properties.setProperty("log4j.appender.file.layout", "org.apache.log4j.PatternLayout");

properties.setProperty("log4j.appender.file.layout.ConversionPattern",

"%d [%t] %-5p %c{1} %C{6} (%F:%L) - %m%n");

properties.setProperty("log4j.appender.file.append", "true");

properties.setProperty("log4j.appender.file.file", "logtest2.log");

PropertyConfigurator.configure(properties);

// 比较同名称的log,结果为true,所以log作为入参不需要传入引用,直接get即可。

System.out.println(Module1.log.equals(ServiceImpl_1.log));

System.out.println(Module2.log.equals(ServiceImpl_2.log));

// 按模块搜索查看日志,关键词就是模块名称,即上面的Module1,Module2。

// 解决包名类名完全一样,但是在不同模块的日志查询。

Module1.println();

Module2.println();

ServiceImpl_1.println();

ServiceImpl_2.println();

System.out.println("end");

}

public static class Module1 {

public static Log log = LogFactory.getLog(Module1_LogName);

public static void println() {

log.info("this is module1");

}

}

public static class Module2 {

public static Log log = LogFactory.getLog(Module2_LogName);

public static void println() {

log.info("this is module2");

}

}

public static class ServiceImpl_1 {

public static Log log = LogFactory.getLog(Module1_LogName);

public static void println() {

log.info("this is service");

}

}

public static class ServiceImpl_2 {

public static Log log = LogFactory.getLog(Module2_LogName);

public static void println() {

log.info("this is service");

}

}

}

练习代码看这里


上一篇:springext练习


下一篇:go语言项目如何引用依赖Github上的开源项目