Why is Logger static most of the time?

Why is it considered "best practice" in java to use Logger

with static

like:

public static final Logger LOGGER = LoggerFactory.getLogger(....)

      

I can't figure out why. If I use one instance of the logger and pass it to the constructor, it shouldn't have a performance impact.

Can someone explain why? Is it better than DI? If so, why? There are many opinions. Or is it just "because of the java way"?

+3


source to share


4 answers


To avoid unnecessary creation of multiple instances. Typically, one is Logger

sufficient because it writes to one logical location (which can be multiple physical output streams). If you pass a method to a Logger

method, it appears to be supposed to handle the logging programmatically. Instead, I suggest you use your own log configuration mechanism to enable and disable messaging.



+3


source


I claim that you can achieve the same results with setter injection and dependency injection container .

You can still have very simple logging, it is just not static and therefore can be configured and changed in the DI container without setting up some kind of global static state of some kind of global static factory, which is usually very difficult to test and maintain.



However, I know that making it static is pragmatic. I'm just arguing that doing this DI way is cleaner.

+2


source


This is because proper logging is very difficult. Consider the Single Responsibility Principle :

In object-oriented programming, the Single Responsibility Principle states that each class should be responsible for one piece of functionality provided by the software, and that responsibility should be fully encapsulated by the class. All of his services must be closely aligned with this responsibility.

However, if you think about it, the code that handles the logging will never be the primary responsibility of the class. The class will do what it does, and then you can add some registration statements, which are the second responsibility of the class. How can this be solved?

One way is to use Aspect Oriented Programming and Reflection to go through your code and try to log actions as they occur, but this is ugly and needs to be approached to the language. Another way would be to add objects Logger

to the class construction, but this has several disadvantages:

  • You can do this without adding a lot of templates if you are using DI framework
  • You still need to customize the name Logger

    , which means the injection now depends on the class it is injected into.
  • Again, if you are not using a DI framework, you need to somehow maintain access to the same object Logger

    when you create the object, or you create many duplicate objects that stand in memory, without any advantages, which are even more boilerplate code.

So what to do? The easiest way is to let all classes have static access to the object Logger

. SLF4J provides this mechanism with LoggerFactory.getLogger()

as you correctly point out. This is one line of code that allows you to completely customize the behavior in all your classes to use the logging functionality using the Factory Pattern . You don't need to worry about injection, reflection, or AOP setup; it's simple, simple, and works.

+1


source


private - so that no other class can hijack your logger

static - this way there is only one log instance per class and also avoid trying to serialize logs

final - no need to change the registrar for the lifetime of the class

However, there is an interesting exception to these rules:

protected final Logger log = LoggerFactory.getLogger (getClass ());

The first method allows you to use the same registrar name (actual class name) in all classes in the entire inheritance hierarchy. Therefore, if Bar expands Foo, both will be logged to Bar logger. Some people find it more intuitive.

The advantage of the non-static form is that you can declare it in the (abstract) base class as it should without worrying about the right class name being used

However, its disadvantage is obviously that a whole new log instance will be created for each instance of the class.

On the other hand, if you get the logger using a factory, which in turn can cache already created log instances, then using a non-static form won't add too much overhead. Log4j, for example, has a LogManager for this purpose.

protected Log log = LogManager.getLogger (getClass ());

0


source







All Articles