2016-06-02 17 views
0

컨트롤러 클래스에서 종속성 삽입을 사용하여 인스턴스를 생성했습니다. 내가 다른 곳에서 @inject annotation을 사용하여 그 객체를 사용하려고하면 null 값을 얻는다. 여기 내 코드 스켈레톤이있다.@Inject 개체 null : 종속성 삽입 재생

@singleton 
class ServiceClient(ws: WSClient, config: Configuration) { 
def get response() {...} 
} 

class App @Inject()(client: ServiceClient) extends Controller { 

    def getItems = Action { 
    Obj() 
    } 
} 

case class Obj() { 

    @Inject 
    var client: ServiceClient = _ 
    def doStuff() { 
    client.getResponse() //client is null so get null pointer exception. 
    .... 
    } 
} 

@Inject in Obj는 작동하지 않는 것 같습니다. 내 클라이언트 개체는 항상 null입니다. (클라이언트를 Obj에 param으로 전달하고 싶지 않습니다.) 제 생각에는 Controller에 생성 된 ServiceClient 객체가 Obj()에 주입되어야한다는 것이 었습니다. 내가 뭘 잘못 했니?

갱신

컨트롤러의 Obj을 주입이 옵션을 선택하지 않습니다. (내 애플 리케이션에서 Obj는 런타임에 내 일부 복잡한 규칙, 반사를 사용하여 인스턴스입니다.) 또한 Obj에 생성자 주입을하고 싶지 않아요. 컨트롤러 외부에서 ServiceClient의 필드 주입을 찾고 있습니다.

갱신 2는 내가 확대 개체 클래스에

var client: ServiceClient = play.api.Play.current.injector.instanceOf(classOf[ServiceClient]) 

을 사용하여 문제를 해결할 수 있었다. 그러나 play.api.Play.current는 play 2.5에서 더 이상 사용되지 않습니다. 그래서 나는 여전히 경고가 붙어 있습니다.

답변

1

DI 프레임 워크에 대해 묻지 않고 클래스 인스턴스에 종속성을 주입 할 수 없습니다. 코드에서 Obj을 수동으로 인스턴스화하면 종속성 주입 마법이 발생하지 않습니다. Obj 클래스에 종속성을 주입하려면 인스턴스화가 DI 프레임 워크에 의해 처리되어야합니다. 당신이 여기에서 할 수있는 것은 :

  1. 를 주입 ServiceClient-Obj 생성자 또는 신청 중 하나

    class Obj @Inject() (client: ServiceClient) { 
        // 
    } 
    

    그것은 경우 클래스보다 "데이터"와 같은 소리 때문에 대신하는 경우 클래스의 간단한 클래스를 사용하는 의미가 있습니다 서비스 또는 일부 도우미 클래스보다는 내부에 불변의 데이터가있는 클래스. 사실 Obj 클래스의 현재 정의가 작동해야합니다.

  2. 를 주입 Obj 및 (또는, 필요에 따라) 당신의 앱 클래스에 ServiceClient :

    class App @Inject()(obj: Obj, client: ServiceClient) extends Controller { 
        def getItems = Action { 
        obj.doStuff() 
        } 
    } 
    

내가 사용된다 의존성 주입과 Guice 프레임 워크에 대한 자세한 내용을 읽어보실 것을 권 해드립니다 기본적으로 재생합니다. Guice wiki

+0

감사합니다. 클래스 인스턴스에 종속성을 주입하는 방법에 대해 자세히 설명해 주시겠습니까? – konquestor

+0

흐름은 실제로 DI 프레임 워크에 따라 다릅니다. Guice에서 일반적인 패턴은 1. 클래스 (인터페이스)와 그 구현 (바인딩은 주석을 사용하여 수행 할 수 있음)에 대한 바인딩을 정의하는 모듈 (AbstractModule을 확장하는 클래스)을 정의하고, 2. 해당 모듈에 대한 인젝터를 만듭니다. val injector = Guice.createInjector (new YourModule())'. 3. injector에게 특정 클래스 인스턴스'injector.getInstance (classOf [Obj])'를 요청하십시오. 그래서 인스턴스화는 Guice에 의해 처리됩니다. 또한 [DI 용 Play 문서] (https://www.playframework.com/documentation/2.5.x/ScalaDependencyInjection)를 살펴보십시오. – yahor

+0

Play에서는 보통 인젝터를 직접 만들지 않지만 모듈은 일반적으로 사용됩니다. Play 설정 ('application.conf')에서 모듈을 활성화해야합니다. – yahor