通常我会像这样定义记录器:
private static final Logger logger = LoggerFactory.getLogger(MyClass.class);
但是在使用@Inject
时,我们必须使用非静态和非最终字段,例如:
@Inject
private Logger logger;
即。将在此类的每个实例中创建记录器,记录器也是可变的。可能存在一些让logger静态的方法吗?另外我如何将logger绑定到某个类(我使用从工厂LoggerFactory.getLogger(MyClass.class);
创建logger对象时发送类对象,如何使用注入以相同的方式创建logger?)?
答案 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();
}
}
}