我正处于CDI的初级阶段,并尝试使用字段注入注入接口的实现,如下所示:
AutoService.java
package com.interfaces;
public interface AutoService {
void getService();
}
BMWAutoService.java
package com.implementations;
import javax.inject.Named;
import com.interfaces.AutoService;
@Named("bmwAutoService")
public class BMWAutoService implements AutoService {
public BMWAutoService() {
// TODO Auto-generated constructor stub
}
@Override
public void getService() {
System.out.println("You chose BMW auto service");
}
}
AutoServiceCaller.java
package com.interfaces;
public interface AutoServiceCaller {
void callAutoService();
}
AutoServiceCallerImp.java
package com.implementations;
import javax.inject.Inject;
import javax.inject.Named;
import com.interfaces.AutoService;
import com.interfaces.AutoServiceCaller;
public class AutoServiceCallerImp implements AutoServiceCaller {
@Inject
@Named("bmwAutoService")
private AutoService bmwAutoService;
public AutoServiceCallerImp() {
}
@Override
public void callAutoService() {
bmwAutoService.getService();
}
}
TestDisplayMessage.java
package com.tests;
import com.implementations.AutoServiceCallerImp;
import com.interfaces.AutoServiceCaller;
public class TestDisplayMessage {
public TestDisplayMessage() {
// TODO Auto-generated constructor stub
}
public static void main(String[] args) {
AutoServiceCaller caller = new AutoServiceCallerImp();
caller.callAutoService();
}
}
当我运行TestDisplayMessage.java
时,预期结果将是“您选择了宝马汽车服务”,但我得到如下NullPointerException:
Exception in thread "main" java.lang.NullPointerException
at com.implementations.AutoServiceCallerImp.callAutoService(AutoServiceCallerImp.java:21)
at com.tests.TestDisplayMessage.main(TestDisplayMessage.java:16)
无法弄清楚我在这里错过了什么。请帮忙。谢谢。
答案 0 :(得分:0)
好吧,你似乎误解了CDI的概念 - 这个想法是你将bean生命周期留给了CDI容器。这意味着CDI将为您创建创建配置bean。换句话说,您不应该通过调用new
来创建bean。如果你这样做,CDI不会知道它,也不会注入任何东西。
如果您处于SE环境中,我认为您使用main
方法进行测试,那么您希望使用Weld(CDI实现)SE工件(我猜你这样做)。
在那里,您需要启动CDI容器。请注意,如果您在服务器上开发经典EE应用程序,则不要这样做,因为服务器将为您处理它。现在,启动Weld SE容器的最基本方法是:
Weld weld = new Weld();
try (WeldContainer container = weld.initialize()) {
// inside this try-with-resources block you have CDI container booted
//now, ask it to give you an instance of AutoServiceCallerImpl
AutoServiceCallerImpl as = container.select(AutoService.class).get();
as.callAutoService();
}
现在,你的代码第二个问题。 @Named
的用法适用于EL解析。例如。在JFS页面中,您可以直接访问bean。 您可能想要的是区分多个AutoService
实现并选择给定的实现。因为CDI有限定符。查看this documentation section以获取有关如何使用它们的更多信息。