深入Log4J源码之LoggerRepository和Configurator(二)

2014-11-24 08:39:23 · 作者: · 浏览: 6
比如对“x.y.z.w”Logger实例,它会产生三个ProvisionNode实例(当然如果相应的实例已经存在,则直接添加而无需创建,另外,如果相应节点已经是Logger实例,那么将“x.y.z.w”Logger实例的parent直接指向它即可):ProvisionNode(“x”), ProvisionNode(“x.y”), ProvisionNode(“x.y.z”),他们都存储了“x.y.z.w”Logger实例作为其子节点。

1 class ProvisionNode extends Vector {
2 ProvisionNode(Logger logger) {
3 super();
4 this.addElement(logger);
5 }
6 }
7 final private void updateParents(Logger cat) {
8 String name = cat.name;
9 int length = name.length();
10 boolean parentFound = false;
11 // if name = "x.y.z.w", loop thourgh "x.y.z", "x.y" and "x"
12 for (int i = name.lastIndexOf('.', length - 1); i >= 0; i = name
13 .lastIndexOf('.', i - 1)) {
14 String substr = name.substring(0, i);
15 CategoryKey key = new CategoryKey(substr);
16 Object o = ht.get(key);
17 if (o == null) {
18 ProvisionNode pn = new ProvisionNode(cat);
19 ht.put(key, pn);
20 } else if (o instanceof Category) {
21 parentFound = true;
22 cat.parent = (Category) o;
23 break; // no need to update the ancestors of the closest
24 // ancestor
25 } else if (o instanceof ProvisionNode) {
26 ((ProvisionNode) o).addElement(cat);
27 } else {
28 Exception e = new IllegalStateException(
29 "unexpected object type " + o.getClass() + " in ht.");
30 e.printStackTrace();
31 }
32 }
33 // If we could not find any existing parents, then link with root.
34 if (!parentFound)

35 cat.parent = root;
36 }
3. 如果找到的是ProvisionNode实例,首先使用factory创建新的Logger实例,将该实例添加到ht集合中,然后更新找到的ProvisionNode内部所有Logger的parent字段以及新创建Logger的parent字段。更新过程中需要注意ProvisionNode中的Logger实例已经指向了正确的parent了,所以只要更新那些ProvisionNode中Logger实例指向的parent比新创建的Logger本身层次要高的那些parent属性。比如开始插入“x.y.z”Logger实例,而后插入“x.y.z.w”Logger实例,此时ProvisionNode(“x”)认为“x.y.z”Logger实例和“x.y.z.w”Logger实例都是它的子节点,而后插入“x”Logger实例,那么只需要更新“x.y.z”Logger的父节点为“x”Logger实例即可,而不用更新“x.y.z.w”Logger实例的父节点。

1 final private void updateChildren(ProvisionNode pn, Logger logger) {
2 final int last = pn.size();
3 for (int i = 0; i < last; i++) {
4 Logger l = (Logger) pn.elementAt(i);
5 // Unless this child already points to a correct (lower) parent,
6 // make cat.parent point to l.parent and l.parent to cat.
7 if (!l.parent.name.startsWith(logger.name)) {
8 logger.parent = l.parent;
9 l.parent = logger;
10 }
11 }
12 }
综合起来,getLogger()方法的实现代码如下:

1 public Logger getLogger(String name, LoggerFactory factory) {
2 CategoryKey key = new CategoryKey(name);
3 Logger logger;
4 synchronized (ht) {
5 Object o = ht.get(key);
6 if (o == null) {
7 logger = factory.makeNewLoggerInstance(name);
8 logger.setHierarchy(this);
9 ht.put(key, logger);
10 updateParents(logger);
11 return logger;
12 } else if (o instanceof Logger) {
13 return (Logger) o;
14 } else if (o instanceof ProvisionNode) {
15 logger = factory.makeNewLoggerInstance(name);
16 logger.setHierarchy(this);
17 ht.put(key, logger);
18 updateChildren((ProvisionNode) o, logger);
19