在Spring Controller中实例化Logger时,是否有理由将其声明为静态最终? LogConger不在MyController.class之外使用。我已经看到两个例子在使用,但不明白为什么我应该使用其中一个。
private Logger logger = LoggerFactory.getLogger(MyController.class);
VS
private static final Logger logger = LoggerFactory.getLogger(MyController.class);
答案 0 :(得分:42)
就个人而言,我使用
private final Logger logger = LoggerFactory.getLogger(this.getClass());
这样做的主要优点是我可以将其剪切并粘贴到新类中,而无需更改类的名称。
至于它们是否应该是静态的,请参阅slf4j网站上的Should Logger members of a class be declared as static?,其中说:
我们曾经建议将记录器成员声明为实例变量而不是静态变量。 经过进一步分析,我们不再推荐一种方法而不是另一种方法。
摘自该页面:
静态记录器成员为该类的所有实例花费单个变量引用,而实例记录器成员将为该类的每个实例花费一个变量引用。对于实例化数千次的简单类,可能会有明显的差异。
但是,更新的日志记录系统(例如log4j或logback)支持应用程序服务器中运行的每个应用程序的不同记录器上下文。因此,即使在服务器中部署了log4j.jar或logback-classic.jar的单个副本,日志记录系统也能够区分应用程序并为每个应用程序提供独特的日志记录环境。
更具体地说,每次通过调用LoggerFactory.getLogger()方法检索记录器时,底层日志记录系统将返回适合当前应用程序的实例。请注意,在同一应用程序中,按给定名称检索记录器将始终返回相同的记录器。对于给定名称,将仅为不同的应用程序返回不同的记录器。
如果记录器是静态的,那么只有在将宿主类加载到内存中时才会检索它。如果托管类仅在一个应用程序中使用,则没有太多需要关注的问题。但是,如果托管类在多个应用程序之间共享,那么共享类的所有实例都将登录到应用程序的上下文,这恰好首先将共享类加载到内存中 - 几乎不是用户期望的行为。
有关详细信息,请参阅该页面。
答案 1 :(得分:3)
只为您的班级的每个实例初始化private
字段。但是,private static
字段将在每个类初始化一次。
如果记录器很可能(取决于日志记录实现),在这两种情况下,您将获得相同的记录器实例,并且您将不会使用明显更大的内存量。但是,对于您创建的每个对象,仍会调用LoggerFactory.getLogger
。
答案 2 :(得分:1)
是;因此,该类只有一个记录器,而不是每个实例一个。
无论哪种方式都是私密的,所以在课外使用它与它无关 - 这不是static final
所做的。
答案 3 :(得分:-4)
我只是对这条线感到好奇:
private Logger logger = LoggerFactory.getLogger(MyController.class);
是吗:
LoggerFactory.getLogger(MyController.class)
或:
LoggerFactory.getLogger(MyController.class.getName());
因为第一个将在真实姓名之前返回“class”:
class com.example.MyController (instead of com.example.MyController)