在 Spring Controller 中实例化 Logger 时,是否有任何理由将其声明为 static final? Logger 不在 MyController.class 之外使用。我已经看到这两个例子都在使用,但不明白为什么我应该使用其中一个。
private Logger logger = LoggerFactory.getLogger(MyController.class);
对
private static final Logger logger = LoggerFactory.getLogger(MyController.class);
最佳答案
我个人使用
private final Logger logger = LoggerFactory.getLogger(this.getClass());
这样做的主要优点是我可以将其剪切并粘贴到新的类中,而无需更改类的名称。
至于是否应该是静态的,请看Should Logger members of a class be declared as static? ,来自 slf4j 网站,上面写着:
我们曾经建议将记录器成员声明为实例变量而不是静态变量。 经过进一步分析,我们不再推荐其中一种方法。
取自该页面:
将记录器声明为静态的优点
- 常见且行之有效的成语
- 更少的 CPU 开销:在宿主类初始化时只检索和分配一次记录器
- 更少的内存开销:记录器声明将为每个类消耗一个引用
将记录器声明为静态的缺点
- 对于在应用程序之间共享的库,无法利用存储库选择器。需要注意的是,如果 SLF4J 绑定(bind)和底层 API 随每个应用程序一起提供(不是在应用程序之间共享),那么每个应用程序仍然有自己的日志记录环境。
- 对国际奥委会不友好
将记录器声明为实例变量的优点
- 即使是在应用程序之间共享的库,也可以利用存储库选择器。但是,存储库选择器仅在底层日志记录系统是 logback-classic 时才有效。存储库选择器不适用于 SLF4J+log4j 组合。
- 国际奥委会友好
将记录器声明为实例变量的缺点
- 比将记录器声明为静态变量更不常见的习惯用法
- 更高的 CPU 开销:为托管类的每个实例检索和分配记录器
- 更高的内存开销:记录器声明将消耗每个宿主类实例的引用
说明
静态记录器成员为类的所有实例花费一个变量引用,而实例记录器成员将为类的每个实例花费一个变量引用。对于实例化数千次的简单类,可能会有明显差异。
但是,更新的日志系统(例如 log4j 或 logback)支持在应用服务器中运行的每个应用程序使用不同的记录器上下文。因此,即使在服务器中部署了 log4j.jar 或 logback-classic.jar 的单个副本,日志系统也将能够区分应用程序并为每个应用程序提供不同的日志记录环境。
更具体地说,每次通过调用 LoggerFactory.getLogger() 方法检索记录器时,底层记录系统将返回一个适合当前应用程序的实例。请注意,在同一个应用程序中检索给定名称的记录器将始终返回相同的记录器。对于给定的名称,将仅针对不同的应用程序返回不同的记录器。
如果记录器是静态的,那么它只会在宿主类加载到内存时被检索一次。如果宿主类只在一个应用程序中使用,则无需过多关注。但是,如果托管类在多个应用程序之间共享,那么共享类的所有实例都将登录到应用程序的上下文中,而应用程序恰好首先将共享类加载到内存中——这几乎不是用户期望的行为。
有关详细信息,请参阅该页面。
关于java - 有什么理由在 LogBack Logger 上使用 private 而不是 private final static?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8262310/