当我尝试在枚举中注入我的Logger生成器时,我得到了一个NPE。如何在枚举中注入Logger?
示例:
public enum MyEnum {
HI("Hi there!"),
HELLO("Hello mister!");
@Inject
private Logger log;
private final String greeting;
private MyEnum(String greeting) {
this.greeting = greeting;
// this.log = LoggerFactory.getLogger(this.getClass());
}
public String getGreeting() {
log.debug("Method getGreeting called");
return this.greeting;
}
}
这个课在log.debug()
行给我一个NPE。当我删除@Inject
并取消注释this.log
行时,它就可以正常工作。
Testcase看起来像这样:
@RunWith(Arquillian.class)
public class CoverKindTest {
@Deployment
public static WebArchive createDeployment() {
return ShrinkWrap.create(WebArchive.class, "test.war")
.addClass(MyEnum.class)
.addClass(LoggerProducer.class)
.addAsWebInfResource(EmptyAsset.INSTANCE, "beans.xml");
}
@Test
public void testEnum() {
MyEnum myEnum = MyEnum.HI;
String greeting = myEnum.getGreeting();
assertThat("Should give the greeting.", greeting, is("Hi there!"));
}
}
可以在此处找到此问题的完整可测试项目,MyEnum.class
是原始问题,MyEnum1.class
是无注入的解决方案(正常工作,但不是我要查找的内容)和{{1}是一个建议的答案。
编辑:使用有效的解决方案更新了GitHub仓库。 https://github.com/martijnburger/how-to-inject-a-logger-in-an-enum
答案 0 :(得分:2)
由于枚举是静态的,这种直接注射不起作用。 您可以在枚举类中创建一个新的记录器
private static final Logger log = Logger.getLogger(Myenum.class.getName());
答案 1 :(得分:2)
找到一个有效的解决方案!
我创建了一个帮助类,如下所示:
public class LoggerHelper {
private static Logger logger;
private void injectLogger(@Observes @Initialized(ApplicationScoped.class) Object context,
Logger logger) {
LoggerHelper.logger = logger;
}
public static Logger getLogger() {
return logger;
}
}
现在我可以使用以下方法在Enum中注入记录器:
private final Logger log = LoggerHelper.getLogger();
答案 2 :(得分:0)
不能注射枚举,因为它们是静态的。
如果您仍想要注入(而不是仅仅创建Logger),那么您需要在枚举中创建一个静态类,该类具有setter或构造函数注入。当DI框架调用setter或构造函数时,取其给出的值并将其自己分配给枚举中的静态值。
枚举可以根据需要立即访问它。但要注意,如果您的课程尚未注入,则该值将为null。
这样的事情:
public enum MyEnum {
HI("Hi there!"),
HELLO("Hello mister!");
private static Logger log;
private final String greeting;
private MyEnum(String greeting) {
this.greeting = greeting;
}
public String getGreeting() {
log.debug("Method getGreeting called");
return this.greeting;
}
@Component
public static class InjectionHelper {
@Inject
public InjectionHelper(Logger log) {
MyEnum.log = log;
}
}
}
答案 3 :(得分:-1)
你可以创建一个Singleton Service类(由你自己的DI框架创建 - 比如Spring),在该类中注入这个日志并在你的枚举中使用它。
这是一个有效的示例代码。 (如果您正在使用XML方法,那么用XML替换此类的bean标记,如果您正在使用XML方法。也可以忽略lombok @Getter
注释并用静态getter替换它)
// Service which is actually a Utility class but have DI Managed Beans.
@Service("staticService")
public class StaticService {
@Getter
private static Logger log;
@Inject
StaticService(Logger log) {
StaticService.log = log;
}
}
现在在相应的枚举中:
public String getGreeting() {
StaticService.getLog().debug("Method getGreeting called");
return this.greeting;
}
我在我的一个类(In Spring)中使用了类似的模式,并且注入工作正常。
逻辑:
注意: