使用注释处理延迟绑定到Dagger2图表

时间:2015-04-23 23:37:00

标签: java dependency-injection guice dagger dagger-2

在这个问题中,我谈到了Dagger2。 Dagger2基本上由组件和模块组成。这是一个例子:

假设我有一个界面:

public interface MyCoolService {
  void run();
}

和可能的实施:

public class MyCoolServiceImpl {
   @Override
   void run() {}
}

我可以使用Dagger2生成链接实现与接口:

@Component(modules = {MyModule.class})
@Singleton
public interface Component {    
    MyCoolService getMyCoolService();       
}

@Module
public class MyModule {

    @Provides @Singleton
    MyCoolService provideMyCoolService() {
        return new MyCoolServiceImpl();
    }
}

这是Dagger2的简要介绍。现在假设我有以下界面:

public interface MySecondCoolService {
  void doCoolStuff();
}

代码中没有MySecondCoolServiceImpl的{​​{1}}实现。相反,我有一个注释MySecondCoolService来标记字段和方法。我创建了一个Annotation处理器,它收集所有这些注释并生成实现@JustForCoolStuff的{​​{1}}。

我在注释处理器运行之前知道新接口MySecondCoolServiceImpl。所以我可以将我的组件更改为:

MySecondCoolService

问题是我在代码中还没有实现,我不知道将由注释处理器生成的MySecondCoolService实现的名称。因此,我无法在@Component(modules = {MyModule.class}) @Singleton public interface Component { MyCoolService getMyCoolService(); MySecondCoolService getMySecondCoolService(); } 中使用正确的实现来连接接口。我可以做的是更改我的注释处理器,以便它为我生成一个新模块。我的注释处理器可以生成一个模块(MySecondCoolService),如下所示:

MyModule

再次MyGeneratedModule由注释处理器生成。我在运行注释处理器之前无法访问它也不知道名称。

以下是问题:注释处理器不得不告诉Dagger2 Dagger2应该考虑一个新模块。由于注释处理器无法更改文件,因此无法扩展@Module public class MyGeneratedModule { @Provides @Singleton MySecondCoolService provide MySecondCoolService() { return new MySecondCoolServiceImpl(); } } 注释并将其更改为以下内容:MyGeneratedModule

有没有办法以编程方式将@Component(modules = {MyModule.class})添加到dagger2依赖关系图?我的注释处理器如何告诉Dagger2接口和实现之间应该有新的连接,如上所述?

FORAY: 我知道可以在Google GuiceGoogle Gin中完成类似的事情。这样做的项目是GWTP。那里有一位演示者:

@Component(modules = {MyModule.class, MyGeneratedModule.class})

MyGeneratedModule接口有public class StartPagePresenter extends ... { @NameToken("start") public interface MyProxy extends ProxyPlace<StartPagePresenter> { } ... } 注释。在@NameToken中,您使用演示者和代理连接视图:

ProxyPlace

因为可以看到没有给出AbstractPresenterModule接口的实现。由Generator生成的实现(类似于注释处理器,但用于GWT)。 Generator生成public class ApplicationModule extends AbstractPresenterModule { bindPresenter(StartPagePresenter.class, StartPagePresenter.MyView.class, StartPageView.class, StartPagePresenter.MyProxy.class); ... } 的实现并将其添加到指南/杜松子酒系统:

MyProxy

2 个答案:

答案 0 :(得分:1)

  

有没有办法以编程方式将MyGeneratedModule添加到dagger2依赖图中?

是。在模块中使用构造函数参数。

@Module
public class MyModule {
  private final MyCoolService serviceImpl;

  public MyModule(MyCoolService serviceImpl) {
    this.serviceImpl = serviceImpl;
  }

  @Provides @Singleton
  MyCoolService provideMyCoolService() {
    return new MyCoolServiceImpl();
  }
}

在构建图表时初始化serviceImpl:

DaggerComponent.builder().myModule(new MyModule(serviceImpl)).build();

答案 1 :(得分:0)

嗯,看来你不得不求助于这个反思......

@Module
public class MyGeneratedModule {

    @Provides @Singleton
    MySecondCoolService provide MySecondCoolService() {
        try {
            return (MySecondCoolService) Class.forName("package.MySecondCoolServiceImpl").newInstance(); 
        } catch (Exception ex) { ... }
    }
}