2017-04-07 59 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