Dagger2 Field Injection not working

2019-08-23 02:34发布

I am familiar with Spring dependency injection, but Dagger2 is new to me. I am trying to get a simple java application working but field injection does not work.

I have a class Main, that depends on a class MainBusiness which in turn depends on MainDao.

MainBusiness gets injected into Main fine, but MainDao does not get injected into MainBusiness and throws a NullPointerException.

Here is the MainDao that implements an interface IMainDao

public class MainDao implements IMainDao
{       
    @Inject
    public MainDao()
    {
    }

    public String getResource()
    {
        return "This is the resource you are looking for";
    }
}

Here is the MainBusiness that implements IMainBusiness

public class MainBusiness implements IMainBusiness
{
    // package friendly field.  
    @Inject
    IMainDao mainDao;

    @Inject
    public MainBusiness()
    {
    }

    public String getResource()
    {       
        return mainDao.getResource(); // throws NPE here.
    }

}

Here is the AppModule

@Module
public class AppModule
{   
    /**
     * Provides a singleton instance of the MainDao 
     * 
     * @return
     */
    @Provides
    @Singleton
    public IMainDao providesMainDao()
    {
        return new MainDao();
    }

    /**
     * Provides a singleton instance of the MainBusiness Class
     * 
     * @return
     */
    @Provides
    @Singleton
    public IMainBusiness providesMainBusiness()
    {
        return new MainBusiness();
    }
}

The AppComponent

@Singleton
@Component(modules = {AppModule.class})
public interface AppComponent
{

    /**
     * @param main
     */
    void inject(Main main); 
}

And the Main class

public class Main
{   
    @Inject
    IMainBusiness mainBusiness;

    public Main()
    {
        AppComponent dac = DaggerAppComponent.builder().build();        
        dac.inject(this);       
    }

    public static void main(String args[])
    {
        Main main = new Main();     
        System.out.println(main.mainBusiness.getResource());
    }
}

It throws an NPE on MainBusiness.getResource(MainBusiness.java:14)

What am I missing here? Appreciate any help I can get.

P.S This is a plain Java application. It is not an Android application.

1条回答
走好不送
2楼-- · 2019-08-23 03:14

Field injection will inject the fields of the object you pass in. someComponent.inject(someObject) will then inject the fields of someObject, but it does not inject the dependencies transitively. Hence MainBusiness will still have an uninitialized DAO.

If you call new MainBusiness(); yourself you can't expect Dagger to take care of it. You should use constructor injection, and not call new yourself. Modules are for bindings, or additional setup, and should reduce the boilerplate of calling all the constructors yourself.

I took some liberty to switch to constructor injection and completely remove field injection, since it is not needed for your use case. (Maybe there's some typo, I did not compile it)

@Singleton
public class MainDao implements IMainDao
{       
    @Inject
    public MainDao()
    {
    }
}

@Singleton
public class MainBusiness implements IMainBusiness
{
    private IMainDao mainDao;

    @Inject
    public MainBusiness(IMainDao mainDao)
    {
        this.mainDao = mainDao;
    }
}

@Module
interface AppModule {

    @Binds IMainBusiness bindBusiness(MainBusiness impl);

    @Binds IMainDao bindDao(MainDao impl);

}

@Singleton
@Component(modules = {AppModule.class})
public interface AppComponent
{
    //  -> no reason not to use constructor injection here as well
    Main getMain(); // provision method
}

public class Main
{   

    private IMainBusiness mainBusiness;

    // favor constructor injection
    @Inject
    public Main(IMainBusiness mainBusiness)
    {
        this.mainBusiness = mainBusiness;
    }

    public static void main(String args[])
    {
        AppComponent component = DaggerAppComponent.builder().build()
        Main main = component.getMain();
        System.out.println(main.mainBusiness.getResource());
    }
}

I suggest that you have another look at some guides to make sure you understand the concepts, or you might be creating more work for yourself than necessary. I also wrote a post recently where I try to clear up some misconceptions about Dagger.

查看更多
登录 后发表回答