如何使用Google Guice注入记录器

时间:2013-02-19 09:03:59

标签: java logging guice

通常我会像这样定义记录器:

private static final Logger logger = LoggerFactory.getLogger(MyClass.class); 

但是在使用@Inject时,我们必须使用非静态和非最终字段,例如:

@Inject
private Logger logger;

即。将在此类的每个实例中创建记录器,记录器也是可变的。可能存在一些让logger静态的方法吗?另外我如何将logger绑定到某个类(我使用从工厂LoggerFactory.getLogger(MyClass.class);创建logger对象时发送类对象,如何使用注入以相同的方式创建logger?)?

2 个答案:

答案 0 :(得分:7)

请检查Guice wiki上的Custom Injections,有一个完整的Log4J示例。

编辑:您可以为记录器使用static字段或final字段,但不能使用static final字段。这是一个Java limitation

还要警惕that

  

建议不要注入最终字段,因为其他线程可能看不到注入的值。

没有测试过,但文章中的代码应该适用于静态字段,尽管你可以通过删除MembersInjector并在TypeListener中完成所有操作来改进它(因为静态字段只需要设置一次)。

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

OTOH如果你只是想支持JUL,你可能更善于使用built-in support(正如杰夫所说,我认为你不想要一般的答案,因为你没有特别提到你的JUL问题)。

答案 1 :(得分:3)

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

然而,

Guice允许标记字段为静态,requesting injection of static fields when the Injector is created。这些字段需要保持可变 - final并不意味着“最终除了Guice”。

public class YourClass {
  @Inject static Logger logger;

  /* ... */
}

public class YourModule extends AbstractModule {
  @Override public void configure() {
    /* YourClass.logger will work once you create your Injector. */
    requestStaticInjection(YourClass.class);
  }
}

Guice会自动为您提供java.util.logger.Logger instances,其中嵌入了类名,但这只是因为a special case coded into Guice。如果你想要一个特殊的记录器,就像在this SO question中一样,你需要调查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();
    }
  }
}