Вы здесь:

Dagger — фреймворк для внедрения зависимостей (Dependency Injection, DI) в приложения на платформе Java. Разрабатывался компанией Square, но сейчас поддерживается Google.
Документация: https://dagger.dev/dev-guide/
Github: https://square.github.io/dagger/

Очень примитивный пример: https://github.com/cherepakhin/dagger_simple
Hello World: https://github.com/cherepakhin/dagger_hello_world

Задачи Dagger

  • Автоматическое внедрение зависимостей в объекты (классы, интерфейсы, контексты и другие объекты);
  • Управление жизненным циклом зависимостей;
  • Создание синглтонов (единственных экземпляров) или одноразовых зависимостей (создаются новые экземпляры при каждом запросе);
  • Обработка сложных зависимостей;
  • Модульное тестирование (возможность заменять реальные зависимости на фиктивные или подставные объекты).

Особенности

  • проверяет зависимости на этапе компиляции, в отличие от некоторых других фреймворков, которые используют рефлексию;
  • генерирует код, который обрабатывает создание и предоставление зависимостей в соответствии с определёнными правилами;

Аннотации

Dagger использует аннотации, чтобы пометить классы и методы, которые участвуют в процессе внедрения зависимостей. Некоторые распространённые аннотации:

  • @Module — отмечает модули и классы программного средства (com.sample.app.modules.DependenciesProviderModule.java) (аннотация класса).
  • @Provides — этой аннотацией помечаются методы предоставления зависимостей внутри модулей (com.sample.app.modules.DependenciesProviderModule.java) (аннотация метода).
  • @Named - используется вместе с @Provides для установки имени предоставляемого бина
    @dagger.Provides
    @javax.inject.Named("sql") // предоставление зависимости с именем "sql"
    public static DataSource provideMySqlDataSource() {...}
    
    и в классе, который использует зависимость:
    @Inject
    public DataPrinter(@Named("sql") com.sample.app.interfaces.DataSource sqlSource,
            @Named("file") com.sample.app.interfaces.DataSource fileSource) { ... }
    
  • @Component — используется для интерфейса, который объединяет части процесса внедрения зависимостей (com.sample.app.components.DataPrinterComponent.java) (аннотация класса).
  • @Inject — метка запроса зависимостей, которые должны быть предоставлены фреймворком для внедрения. Может использоваться с конструктором класса, полями класса или методами (com.sample.app.util.DataPrinter.java) (аннотация метода).

Дополнительно понадобятся аннотации из javax.inject:

  • @Inject - для конструкторов и полей классов (аннотация метода)
  • @Singleton - для синглтонов @Provides (аннотация метода)

Introduction to Dagger 2 (www.baeldung.com)

Использование на примере

Hello world: https://github.com/cherepakhin/dagger_hello_world

  • @Module — (см.использование ниже в @Provides) отмечает модули и классы программного средства @dagger.Module DependenciesProviderModule.java.
  • @Provides — этой аннотацией помечаются методы предоставления зависимостей внутри модулей (@dagger.Module DependenciesProviderModule.java).
    package com.sample.app.modules;
    
    import javax.inject.Named;
    
    import com.sample.app.interfaces.DataSource;
    import com.sample.app.interfaces.impl.FileDataSource;
    import com.sample.app.interfaces.impl.MySQLDataSource;
    
    import dagger.Module;
    import dagger.Provides;
    
    /**
     * Предоставляет реализации зависимостей с именами "file" и "sql"
     * зависимости используется в DataPrinter
     */
    @Module
    public class DependenciesProviderModule {
    
        // Реализация зависимости и внесение в контекст (@dagger.Provides) с именем "sql" (@Named("sql"))
        // используется в DataPrinter через @Inject --> @javax.inject.Named("sql") DataSource sqlSource
        @Provides // @Provides - для внесения зависимости в контекст
        @Named("sql")    // внесение в контекст bean с именем "sql"
        public static DataSource provideMySqlDataSource() {
            return new MySQLDataSource();
        }
    
        @Provides
        @Named("file")
        public static DataSource provideFileDataSource() {
            return new FileDataSource();
        }
    }
    
  • @Componentинтерфейс, который объединяет части процесса внедрения зависимостей
    @Component
    DataPrinterComponent
    package com.sample.app.components;
    
    import com.sample.app.modules.DependenciesProviderModule;
    import com.sample.app.util.DataPrinter;
    
    import dagger.Component;
    import dagger.Module;
    
    // Используется в App.java как:
    // DataPrinterComponent dataPrinterComponent = DaggerDataPrinterComponent.builder().build();
    
    // Реализация В DependenciesProviderModule.java так:
    // @Module
    // public class DependenciesProviderModule
    @Component(modules = {DependenciesProviderModule.class})
    public interface DataPrinterComponent {
    
        DataPrinter dataPrinter();
    
    }
    
  • @Inject — метка зависимостей, которые должны быть предоставлены фреймворком для внедрения. Может использоваться с конструктором класса, полями класса или методами DataPrinter.java. (@Named - используется для точного указания имени зависимости, т.к. в контексте две реализации одного интерфейса)
    package com.sample.app.util;
    
    import javax.inject.Inject;
    import javax.inject.Named;
    
    public class DataPrinter {
    
        private com.sample.app.interfaces.DataSource sqlSource;
    
        private com.sample.app.interfaces.DataSource fileSource;
    
        // В конструктор инжектируются (@javax.inject) 2 бина с @Named("sql") и @Named("file")
        // Предоставляет их DependenciesProviderModule через @Provides(@dagger.Provides)
        // с именами (@Named("sql") и @Named("file"))
    
        @Inject
        public DataPrinter(@Named("sql") com.sample.app.interfaces.DataSource sqlSource,
                           @Named("file") com.sample.app.interfaces.DataSource fileSource) {
            this.sqlSource = sqlSource;
            this.fileSource = fileSource;
        }
    
        public void print() {
            System.out.println("------------------------\nDataPrinter.print:");
            try {
                System.out.println("dataFromSQL: " + getDataFromSQL());
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            try {
                System.out.println("dataFromFile: " + getDataFromFile());
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    
        public String getDataFromSQL() throws Exception {
            if (sqlSource == null) {
                throw new Exception("sqlSource is null");
            }
            return sqlSource.read();
        }
    
        public String getDataFromFile() throws Exception {
            if (fileSource == null) {
                throw new Exception("fileSource is null");
            }
            return fileSource.read();
        }
    
    }
    

@Module DependenciesProviderModule.java объявляет два сервиса @Provides @Named("sql") и @Provides @Named("file"). Эти сервисы используются в com.sample.app.util.DataPrinter (см.выше). И вызываются в src/main/java/com/sample/app/App.java:

public class App {

    public static void main(String[] args) {
        // DaggerDataPrinterComponent - generated class by Dagger from interface DataPrinterComponent
        DataPrinterComponent dataPrinterComponent = DaggerDataPrinterComponent.builder().build();
        DataPrinter dataPrinter = dataPrinterComponent.dataPrinter();

        dataPrinter.print();
    }

}

Ссылки: