Java – using annotations to handle delayed binding to dagger2 diagram

On this issue, I talk about dagger 2 Dagger 2 basically consists of components and modules Here is an example:

Suppose I have an interface:

public interface MyCoolService {
  void run();
}

And may implement:

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

I can use dagger2 to link the implementation to the interface:

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

and

@Module
public class MyModule {

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

This is a brief introduction to dagger 2 Now suppose I have the following interface:

public interface MySecondCoolService {
  void doCoolStuff();
}

Mysecondcoolservice does not implement mysecondcoolserviceimpl. In the code Instead, I have an annotations @ justforcoolstuff to mark fields and methods I created an annotation processor that collects all these annotations and generates a mysecondcoolserviceimpl that implements mysecondcoolservice

The compiler knows the new interface mysecondcoolservice before the annotation processor runs So I can change my component to:

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

The problem is that I haven't implemented it in the code. I don't know the implementation name of mysecondcoolservice, which will be generated by the annotation processor Therefore, I cannot use the correct implementation of the connection interface in mymodule What I can do is change my annotation processor to generate a new module for me My annotation processor can generate a module (mygenerated module), as shown below:

@Module
public class MyGeneratedModule {

    @Provides @Singleton
    MySecondCoolService provide MySecondCoolService() {
        return new MySecondCoolServiceImpl();
    }
}

Again, mygeneratedmodule is generated by the annotation processor Before running the annotation processor, I had no access, and I didn't know the name

Here's the problem: the annotation processor has to tell dagger2 that there is a new module that dagger2 should consider Because the annotation processor cannot change the file, the @ component (modules = {mymodule. Class}) annotation cannot be extended and changed as follows: @ component (modules = {mymodule. Class, mygeneratedmodule. Class})

Is there a way to programmatically add mygeneratedmodule to the dagger2 dependency diagram? How does my annotation processor tell dagger2 that, as mentioned above, there should be a new wiring between the interface and the implementation

Raid: I know such things can be done in Google Guice and Google gin One such project is gwtp You have a Presenter:

public class StartPagePresenter extends ... {
    @NameToken("start")
    public interface MyProxy extends ProxyPlace<StartPagePresenter> {
    }
    ...
}

It has a @ nametoken comment on the proxyplace interface In your abstractpresentermodule, you associate views with presenters and delegates:

public class ApplicationModule extends AbstractPresenterModule {

        bindPresenter(StartPagePresenter.class,StartPagePresenter.MyView.class,StartPageView.class,StartPagePresenter.MyProxy.class);
       ...
}

Therefore, you can see that the implementation of myproxy interface is not given The implementation created by the generator (similar to the annotation processor, but for GWT) Generator generates startpagepresenter Implement myproxy and add it to the guide / gin system:

public class StartPagePresenterMyProxyImpl extends com.gwtplatform.mvp.client.proxy.ProxyPlaceImpl<StartPagePresenter> implements buddyis.mobile.client.app.start.StartPagePresenter.MyProxy,com.gwtplatform.mvp.client.DelayedBind {

  private com.gwtplatform.mvp.client.ClientGinjector ginjector;
    @Override
    public void delayedBind(Ginjector baseGinjector) {
      ginjector = (com.gwtplatform.mvp.client.ClientGinjector)baseGinjector;
      bind(ginjector.getPlaceManager(),ginjector.getEventBus());
      presenter = new CodeSplitProvider<StartPagePresenter>( ginjector.getbuddyismobileclientappstartStartPagePresenter() );
    ...
    }
  }

Solution

Yes Use a constructor parameter in your module

@Module
public class MyModule {
  private final MyCoolService serviceImpl;

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

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

When you build a graph, serviceimpl is initialized:

DaggerComponent.builder().myModule(new MyModule(serviceImpl)).build();
The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>