Dagger2 源码简析

作者: maimingliang | 来源:发表于2016-12-25 23:16 被阅读542次

    Dagger2是首个使用生成代码实现完整依赖注入的框架,极大减少了使用者的编码负担。
    我们去看看Dagger2 是如何为我们注入对象的。

    假设我们需要在MainActivity中注入对象DataManager:

    public class MainActivity extends AppCompatActivity {
    
        @Inject
        DataManager dataManager;
    
    }
    

    使用@Inject标志被注入的对象dataManager(注意dataManager不能为private)

    Dagger2中,负责提供依赖的组件被称为Module。
    创建Module类,如下:

    @Module
    public class AppModule {
    
    
        /**
         * 带@Provides 注解 ,说明该方法是提供依赖
         * @return
         */
        @Provides
        public DataManager provideManager() {
            return new DataManager();
        }
    
    }
    
    

    使用@Module注解来标识类型为module,并用@Provides标识提供依赖的方法。

    Dagger2中,我们需要Component 来连接 Module 和 @Inject 来完成对象的注入:
    创建 Component接口:

    
    @Component(modules = {AppModule.class})
    @Singleton
    public interface AppComponent {
    
        void inject(MainActivity activity);
    }
    
    

    使用@Component注解来标识类型为Component,参数modules 可以依赖多个module。
    接口中的inject方法需要该注入对象所在的类作为参数。注意:这里必须是注入对象所在的类MainActivity,而不可以写成其父类。

    编译。

    Dagger2 会生成一些辅助类。

    带@Component注解 :生成 Dagger_(带@Component注解接口名称)。这里是AppComponent。因此会生成 Dagger_AppComponent;

    带@Module 注解 :生成 (带@Mudule类名)_(带@Provides注解的方法名)Factory。这里是 AppModule_ProvideManagerFactory

    带@Inject 注解:生成 (需要注入对象所在的类名)_MembersInjector。
    这里是MainActivity_MembersInjector。

    类图:

    03.png

    在MainActivity中会调用以下代码:

    
     DaggerAppComponent
                    .builder()
                    .appModule(new AppModule())
                    .build()
                    .inject(this);
    
    

    去看看DaggerAppComponent源码:

    05.png
    1. 调用build方法创建出DaggerAppComponent实例。
    2. 在创建DaggerAppComponent实例时,调用了initialize(builder),创建AppModule_ProvideManagerFactory 和MainActivity_MembersInjector 实例,调用了相对应create的方法。

    MainActivity_MembersInjector 源码:

    06.png
    1. 调用create的方法创建实例时 传入了 AppModule_ProvideManagerFactory 作为参数。

    2. 但 .inject(this)方法时,调用了injectMembers方法,看到这个方法,可以知道为什么datamanage 不能为private和为什么调用inject方法传参数时不能写父类了。

    3. dataManage 实例的创建调用了AppModule_ProvideManagerFactory的get方法。

    看看AppModule_ProvideManagerFactory的源码:

    04.png

    可以看到,get方法其实调用了AppModule 的provideManager方法,而这个方法new DataManager();完成对象的注入。

    这就是Dagger2 为我们注入对象处理的流程。

    我们在MainActivity 再注入一个对象Person,看看Dagger2 生成了怎么样的辅助类。

    修改如下:
    MainActivity :

    
    public class MainActivity extends AppCompatActivity {
    
        @Inject
        DataManager dataManager;
    
        @Inject
        Person person;
    }
    
    

    修改AppModule:

    
    @Module
    public class AppModule {
    
    
        /**
         * 带@Provides 注解 ,说明该方法是提供依赖
         * @return
         */
        @Provides
        public DataManager provideManager() {
            return new DataManager();
        }
    
    
        @Provides
        public Person providePerson(){
            return new Person();
        }
    
    
    }
    
    

    类图:

    08.png

    如果是多层依赖 又会生成什么辅助类?

    添加 UserModule :

    
    @Module
    public class UserModule {
    
    
        @Provides
        public User provideUser(){
            return new User();
        }
    }
    
    

    修改AppComponent

    
    @Component(modules = {AppModule.class,UserModule.class})
    @Singleton
    public interface AppComponent {
    
        void inject(MainActivity activity);
    }
    
    

    修改MainActivity

    
    public class MainActivity extends AppCompatActivity {
    
    
        @Inject
        DataManager dataManager;
    
    
        @Inject
        Person person;
    
    
        @Inject
        User user;
    
    }
    
    

    类图:

    09.png

    可以看出

    1. Component 只是 Module 和 Inject 中间的桥梁
    2. Module 相当于简单工厂,提供了各种依赖

    辅助类的生成规则:

    带@Component注解 :生成 Dagger_(带@Component注解接口名称)。这里是AppComponent。因此会生成 Dagger_AppComponent;

    带@Module 注解 :生成 (带@Mudule类名)_(带@Provides注解的方法名)Factory。这里是 AppModule_ProvideManagerFactory

    带@Inject 注解:生成 (需要注入对象所在的类名)_MembersInjector。
    这里是MainActivity_MembersInjector。

    END。

    相关文章

      网友评论

        本文标题:Dagger2 源码简析

        本文链接:https://www.haomeiwen.com/subject/hetrvttx.html