Generic way of getLogger from log4j.Logger

2019-03-15 10:16发布

问题:

Instead of specifying the class name on each class:

log = Logger.getLogger(Foo.class);
log = Logger.getLogger(Bar.class);
log = Logger.getLogger(Test.class);

Will it be OK to use :

log = Logger.getLogger(this.getClass());

What will be the implications?

回答1:

If you create a subclass, the log messages will get logged to the subclass's logger.

package pkgone;
public class SuperType {
    private Logger log = Logger.getLogger(this.getClass());
    public void someAction() {
        log.info("Doing something");
    }
}

.

package pkgtwo;
import pkgone.SuperType;
public class SubType extends SuperType {
    // for instances of SubType, the log object in SuperType
    // will get initialized with SubType's class object
}

.

// some code somewhere that uses SubType
SubType obj = new SubType();
obj.someAction();

In the above example, "Doing something" will get logged to the pkgtwo.SubType logger instead of pkgone.SuperType logger, which may or may not be what you want.



回答2:

Try this way to look up a generic class...

private static final Log LOGGER = Logger.getLogger(MethodHandles.lookup().lookupClass());

The best part is you can use this method statically.



回答3:

If you don't want to repeat to make the logger and want to avoid write a wrong class name, there's @Log of Project Lombok.

If you don't mind using one more library in your project, you can simply add a logger with a simple annotation.

import lombok.extern.java.Log;
import lombok.extern.slf4j.Slf4j;

@Log
public class LogExample {    
  public static void main(String... args) {
    log.error("Something's wrong here");
  }
}


回答4:

Sure that seems fine.

Be aware that one implication is that if you may have trouble using the log from a static context - It may not be initialized or it may not be visible



回答5:

+1 for sublass instances that call a super method, the logger will be the sub class.

Also if you are applying this as a logging template for your classes, if your class is abstract - your this.getClass will fail as you do not have an instance of this class.



回答6:

Using log factory from Apache commons:

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.Logger;

public class SomeNewClass {
...
private final Log logger = LogFactory.getLog(this.getClass());
...
}

Don't have to do anything else. Not sure LogFactory was available at time of question post. If you don't want to use LogFactory you could also simply use private final with the getClass().

private final Logger log = Logger.getLogger(this.getClass()); 

No reason to create subclasses unless you want a heirarchy of your logging which could also be done with manipulation of the log configuration file (log4j.xml if that's what you are using). You just can't use this.getClass() when the logger is defined as static. Without static or private final you leave the logger open to dangerous possible changes which you don't want.



回答7:

There is no implications as I know. As per Matt comment, I guess, thats the right behaviour which everyone wants it.



标签: java log4j