#java #dependency-injection #dagger-2
#java #внедрение зависимостей #dagger-2
Вопрос:
Привет, я пытаюсь изучить именованную инъекцию в Dagger2
Вот мои классы Java, но ни один из них, похоже, не работает. Чего я хочу, так это того, что на основе аннотации @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.java
и ServerComponent.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();
}
}
Ответ №1:
Ваша основная проблема, похоже, связана с тем фактом, что вы ожидаете в классе TestInject
a Server
named, audio
в то время как ваш провайдер возвращает AudioServer
, поэтому dagger не может удовлетворить вашу зависимость.
Действительно, не забывайте, что аннотация @Named
используется для различения 2 объектов одного и того же типа, другими словами, вы можете аннотировать с помощью @Named("audio")
разных поставщиков, если они не возвращают один и тот же тип. Созданный объект затем будет идентифицирован по его типу и имени.
Итак, например, вот один из способов решить вашу проблему:
Класс TestInject
:
public class TestInject {
...
public TestInject() {
// Needed to inject your dependencies
ServerComponent component = DaggerServerComponent.builder()
.build();
component.inject(this);
}
...
}
Класс ServerComponent
@Singleton
@Component(modules = ServerModule.class)
public interface ServerComponent {
void inject(TestInject inject);
}
Класс ServerModule
@Module
public class ServerModule {
@Provides
@Named("audio")
@Singleton
public Server provideAudioServer() {
return new AudioServer();
}
@Provides
@Named("video")
@Singleton
public Server provideVideoServer() {
return new VideoServer();
}
}
Даже с обновлением вашего вопроса ваш модуль должен быть таким, как я предлагаю, в противном случае он не будет компилироваться по той же причине, что описана ранее.
Комментарии:
1. как бы выглядел мой компонентный класс, m не понятный модуль, я допустил ошибку, должен был быть Super interface, как вы ответили, не могли бы вы, пожалуйста, рассказать, как бы выглядел component class.
2. если я не добавлю аннотацию @Named к серверному компоненту, это не будет компилятором, компонент отвечает за предоставление объектов.