2017-04-07 33 views
0

我在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(); 
} 

A utoServiceCallerImp.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

好吧,你似乎误解了CDI的概念 - 这个想法是你把bean的生命周期留给了CDI容器。这意味着CDI将创建为为你处置豆类。换句话说,你是而不是应该通过调用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