Java 如何使用GoogleGuice注入记录器

Java 如何使用GoogleGuice注入记录器,java,logging,guice,Java,Logging,Guice,我通常这样定义记录器: private static final Logger logger = LoggerFactory.getLogger(MyClass.class); 但是当使用@Inject时,我们必须使用非静态和非final字段,如: @Inject private Logger logger; i、 e.将在此类的每个实例中创建记录器,记录器也是可变的。是否存在使记录器静态的方法?另外,我如何将记录器绑定到特定类(我在从factory创建记录器对象时使用send class

我通常这样定义记录器:

private static final Logger logger = LoggerFactory.getLogger(MyClass.class); 
但是当使用
@Inject
时,我们必须使用非静态和非final字段,如:

@Inject
private Logger logger;
i、 e.将在此类的每个实例中创建记录器,记录器也是可变的。是否存在使记录器静态的方法?另外,我如何将记录器绑定到特定类(我在从factory创建记录器对象时使用send class对象
LoggerFactory.getLogger(MyClass.class);
,如何使用注入以相同的方式创建记录器?

请查看Guice wiki,这里有一个完整的Log4J示例

编辑:您可以为记录器使用
静态
字段或
最终
字段,但不能使用
静态最终
字段。这是一个Java

也要警惕:

不建议注入最终字段,因为注入的值可能对其他线程不可见

我还没有测试过这一点,但是本文中的代码应该可以很好地用于静态字段,尽管您可以通过去掉MembersInjector并在TypeListener中执行所有操作来改进它(因为静态字段只需要设置一次)

使用
requestStaticInjection()
将迫使您在模块文件中列出所有类-这不是一个好主意,因为您很快就会忘记添加一个类


如果您只是想支持JUL,那么最好使用(正如Jeff所提到的,我假设您不想要一个一般性的答案,因为您在问题中没有特别提到JUL)。

在设计依赖注入应用程序时,通常,最佳实践是尽可能避免静态字段和方法。这使得您的依赖关系更加清晰,并且在测试期间以及随着应用程序的发展,更容易用其他实例替换真正的依赖关系。因此,理想的行为是尽可能避免静态方法和字段(包括记录器)

然而,Guice允许标记字段静态和静态。字段需要保持可变--
final
并不意味着“除了Guice之外的final”

Guice会自动为您提供嵌入其中的类名,但这只是因为。如果您想要一个特殊的记录器,如中所示,您需要研究Jakub链接到的自定义注入——但是如果整个目标是集中记录器创建,以便您可以在一个地方控制它,那么您也可以将其重构为Guice之外的静态工厂

@LogToFile
public class YourClass {
  private static final Logger logger = YourLoggerFactory.create(YourClass.class);

  /* ... */
}

public class YourLoggerFactory {
  private YourLoggerFactory { /* do not instantiate */ }

  public Logger create(Class<?> clazz) {
    if (clazz.getAnnotation(LogToFile.class) != null) {
      return someImplementation(new File(...));
    } else {
      return someOtherImplementation();
    }
  }
}
@LogToFile
公共课你的课{
私有静态最终记录器Logger=YourLoggerFactory.create(YourClass.class);
/* ... */
}
公共类工厂{
私有YourLoggerFactory{/*不实例化*/}
公共记录器创建(clazz类){
if(clazz.getAnnotation(LogToFile.class)!=null){
返回一些实现(新文件(…);
}否则{
返回someOtherImplementation();
}
}
}

注入记录器的原因是什么?这只是为了避免某些类型的输入吗?如果您想测试是否写入了某些日志行,那么构造函数注入一个记录器可能会很有用。我发现链接文章缺少几个方面:1)需要一个新的注释。对于JUL,您可以使用@Inject(java.Inject.Inject和Guice的一个)。2) 不支持构造函数注入,3)不支持方法注入4)超类仅由注释中的黑客支持。到目前为止的总结:JUL支持是特殊的,不能以相同的方式和质量转移到其他日志框架。很抱歉,我发现这对我的anwser没有建设性或相关性。1) 不,这不是你可以放弃检查并注入所有记录器字段2)是的,但是你希望Guice如何工作?3) 它是受支持的,你可以用你想要的任何方式(例如寻找方法)检查这个类。我的观点与你的答案相关,就是:链接的文章有它的缺点。那里提出的解决方案不支持注入,而Guice支持其他地方的注入。这些分歧应该在事前就明确,而不是事后才明确。特别是问题的最后一部分(“如何创建…”)和使用
@Inject
似乎正好解决了这个问题。
我列举了我在类似案例中遇到的三个问题。这并不反对你,但只适用于所有想探索该解决方案的人——如果他们说“我可以接受这些东西。”好吧——欢迎。为了说明你的观点:1)如果你根本不使用注释,那么你就更偏离了Guice的正常操作模式。当字段被注入时,我称之为“令人惊讶的行为”(好的框架应该避免),没有任何迹象表明为什么、何时以及由谁注入。您不能像在其他地方一样使用
@Inject
。试试看。2) 这正是缺少的一点(或链接),Guice处理JUL的方式与其他人不同,没有一个已知的解决方法。3) 很多事情都可以做到,但是链接文章没有做到。这些事情都是正确的(除了4),但是没有办法在Guice中绕过它们。如果问题是关于任何DI,那么它们都是相关的,但是由于这是一个关于向记录器注入Guice的问题,我认为抱怨Guice设计选择是没有意义的@4) 我认为把这些叫做“黑客”是没有道理的——这是计算机编程。我假设任何阅读本文的人都已经习惯了Java反射的工作方式。您的解决方案有一个缺点,在您的示例中,类的名称,
Yourclass.class
,必须在所有应用程序中以一致的方式提供。这可能正是集中式注入被认为是有帮助的原因之一——如果有适当的注入支持,这个问题就不会存在。@A.H.请注意,提供程序或依赖项确定其注入站点的能力是有限的。在实例字段中,您可以使用
this
,但在静态上下文中,Java没有比类名本身更短的语法。当您找到或创建“
@LogToFile
public class YourClass {
  private static final Logger logger = YourLoggerFactory.create(YourClass.class);

  /* ... */
}

public class YourLoggerFactory {
  private YourLoggerFactory { /* do not instantiate */ }

  public Logger create(Class<?> clazz) {
    if (clazz.getAnnotation(LogToFile.class) != null) {
      return someImplementation(new File(...));
    } else {
      return someOtherImplementation();
    }
  }
}