Dagger2 Named(@Named) 多态或不同对象注入

Dagger2 Named(@Named) Injection with polymorphism or different object

你好,我正在尝试研究 Dagger2 中的命名注入

这是我的 Java 类,但其中 none 似乎有效。 我想要的是基于@Named 注释我希望得到不同的对象。

public interface Server {

    public void start();

    public void stop();

    public String request(String request);
}

public abstract class AbstractServer implements Server {

    private boolean started;

    @Override
    public void start() {
        started = true;
    }

    @Override
    public void stop() {
        if (!started) {
            throw new IllegalStateException("Server was not started");
        }
    }
}

public class AudioServer extends AbstractServer{

     @Override
    public String request(String request) {
        return "Response from Audio server: " + request;
    }

}

public class VideoServer extends AbstractServer {

    @Override
    public String request(String request) {
        return "Response from Video server: " + request;
    }
}

@Module
public class ServerModule {

    public ServerModule() {
    }

    @Provides
    @Named("audio")
    @Singleton
    AudioServer provideAudioServer() {
        return new AudioServer();
    }

    @Provides
    @Named("video")
    @Singleton
    VideoServer provideVideoServer() {
        return new VideoServer();
    }
}

请不要ServerComponent.java没有编译

@Singleton
@Component(modules = {ServerModule.class})
public interface ServerComponent {

    AudioServer provideAudioServer();

    VideoServer provideVideoServer();

    void inject(TestInject inject);

}

public class TestInject {

    private static final Logger logger = Logger.getLogger(TestInject.class.getSimpleName());

    @Inject
    @Named("audio")
    Server audioServer;

    public TestInject() {
//        ServerComponent component = DaggerServerComponent.builder()
//                .build();
//        component.inject(this);
    }

    public void test() {
        String serverResponse = null;
        if (audioServer != null) {
            serverResponse = audioServer.request("game.mp3");
            logger.warning(serverResponse);
        } else {
            serverResponse = "Failure";
            logger.info(serverResponse);
        }
    }

    public static void main(String[] args) {
        TestInject inject = new TestInject();
        inject.test();
    }
}

已编辑 请参阅 TestInject.javaServerComponent.java

中的答案
public interface Server {

    public void start();

    public void stop();

    public String request(String request);
}

public abstract class AbstractServer implements Server {

    private boolean started;

    @Override
    public void start() {
        started = true;
    }

    @Override
    public void stop() {
        if (!started) {
            throw new IllegalStateException("Server was not started");
        }
    }
}

public class AudioServer extends AbstractServer{

     @Override
    public String request(String request) {
        return "Response from Audio server: " + request;
    }

}

public class VideoServer extends AbstractServer {

    @Override
    public String request(String request) {
        return "Response from Video server: " + request;
    }
}

@Module
public class ServerModule {

    public ServerModule() {
    }

    @Provides
    @Named("audio")
    @Singleton
    AudioServer provideAudioServer() {
        return new AudioServer();
    }

    @Provides
    @Named("video")
    @Singleton
    VideoServer provideVideoServer() {
        return new VideoServer();
    }
}

请不要ServerComponent.java没有编译

@Singleton
@Component(modules = {ServerModule.class})
public interface ServerComponent {

    @Named("audio")
    Server provideAudioServer();

    @Named("video")
    Server provideVideoServer();

    void inject(TestInject inject);
}

    public class TestInject {

    private static final Logger logger = Logger.getLogger(TestInject.class.getSimpleName());

    @Inject
    @Named("audio")
    Server audioServer;

    @Inject
    @Named("video")
    Server videoServer;

    public TestInject() {
        ServerComponent component = DaggerServerComponent.builder()
                .build();
        component.inject(this);
    }

    public void testAudioServer() {
        String serverResponse = null;
        if (audioServer != null) {
            serverResponse = audioServer.request("game.mp3");
            logger.warning(serverResponse);
        } else {
            serverResponse = "audio server Failure";
            logger.info(serverResponse);
        }
    }

    public void testVideoServer() {
        String serverResponse = null;
        if (videoServer != null) {
            serverResponse = videoServer.request("movie.mp4");
            logger.warning(serverResponse);
        } else {
            serverResponse = "Video server Failure";
            logger.info(serverResponse);
        }
    }

    public static void main(String[] args) {
        TestInject inject = new TestInject();
        inject.testAudioServer();
        inject.testVideoServer();
    }
}

您的主要问题似乎与您期望 class TestInject 一个名为 audioServer 而您的提供者 return s AudioServer 所以 dagger 不能满足你的依赖。

确实不要忘了注解@Named是用来区分2个对象同类型的,也就是说可以用[=18=注解] 不同的提供者,只要他们不 return 同一类型。然后生成的对象将由其类型和名称标识。

例如,这是解决问题的一种方法:

class TestInject:

public class TestInject {
    ...

    public TestInject() {
        // Needed to inject your dependencies
        ServerComponent component = DaggerServerComponent.builder()
            .build();
        component.inject(this);
    }
    ...
}

classServerComponent

@Singleton
@Component(modules = ServerModule.class)
public interface ServerComponent {
    void inject(TestInject inject);
}

classServerModule

@Module
public class ServerModule {

    @Provides
    @Named("audio")
    @Singleton
    public Server provideAudioServer() {
        return new AudioServer();
    }

    @Provides
    @Named("video")
    @Singleton
    public Server provideVideoServer() {
        return new VideoServer();
    }
}

即使你的问题更新了,你的模块也应该是我建议的,否则它不会因为前面描述的相同原因而编译。