(12) Dagger2 @IntoMap case analysis

Code example
// 父类
abstract class Animal {
    
    
    // 抽象方法
    abstract void sleep();
}
// 子类
class Tiger extends Animal {
    
    
    @Inject
    public Tiger() {
    
    
    }
    @Override
    public void sleep() {
    
    
        System.out.println("Tiger sleeping");
    }
}
// 子类
class Cat extends Animal {
    
    
    // 将Cat对象加入注射器中
    @Inject
    public Cat() {
    
    
    }
    @Override
    public void sleep() {
    
    
        System.out.println("Cat sleeping");
    }
}
@Module
abstract class ZooModule {
    
    
    @IntoMap // 该注解的意思是将Animal对象注入Map集合中
    @AnimalKey(Tiger.class) // 以Tiger.class对象作为key
    @Binds // 该注解可以视为@Provides
    abstract Animal providerTiger(Tiger tiger);
    @IntoMap
    @AnimalKey(Cat.class)

    @Binds
    abstract Animal providerCat(Cat cat);
}
@Component(modules = {
    
    ZooModule.class})
interface ZooComponent {
    
    
    void inject(Zoo zoo);
}
public class Zoo {
    
    
    @Inject
    Map<Class<? extends Animal>, Animal> map;
    @Test
    public void 案例十() {
    
    
        DaggerZooComponent.create().inject(this);
        map.forEach(new BiConsumer<Class<? extends Animal>, Animal>() {
    
    
            @Override
            public void accept(Class<? extends Animal> aClass, Animal animal) {
    
    
                System.out.println(aClass);
                animal.sleep();
            }
        });
    }
}
Dagger2 generated code reading

The main analysis is how to generate a Map<Class<? extends Animal>, Animal> collection

Looking at the code generated by Degger2 based on the above case, the generated code is in the build\generated\sources\annotationProcessor\..folder.

  • Analyzing the injected logic, you can basically figure it out. .inject(this)The logic after calling the injection is as follows:
final class DaggerZooComponent implements ZooComponent {
    
    
    @Override
    public void inject(Zoo zoo) {
    
    
      injectZoo(zoo);
    }
    private Zoo injectZoo(Zoo instance) {
    
    
        // getMapOfClassOfAndAnimal() :该方法生成一个Map集合
        Zoo_MembersInjector.injectMap(instance, getMapOfClassOfAndAnimal());
        return instance;
    }
    private Map<Class<? extends Animal>, Animal> getMapOfClassOfAndAnimal() {
    
    
        // 这里很@IntoSet注解那段太像了.
        // 下面分析下如何创建一个Map集合
        return MapBuilder.<Class<? extends Animal>, Animal>newMapBuilder(2).put(Tiger.class, new Tiger()).put(Cat.class, new Cat()).build();
    }
}
  • MapBuilder.<Class<? extends Animal>, Animal>newMapBuilder(2)
public final class MapBuilder<K, V> {
    
    
    public static <K, V> MapBuilder<K, V> newMapBuilder(int size) {
    
    
      return new MapBuilder<>(size);
    }
    private MapBuilder(int size) {
    
    
      // 创建了一个LinkedHashMap
      contributions = newLinkedHashMapWithExpectedSize(size);
    }
}
  • .put(Tiger.class, new Tiger())
public MapBuilder<K, V> put(K key, V value) {
    
    
  // 将key与value添加到LinkedHashMap
  contributions.put(key, value);
  return this;
}
  • .build()
public Map<K, V> build() {
    
    
  switch (contributions.size()) {
    
    
    case 0:
      return Collections.emptyMap();
    default:
      // 将contributions返回  
      return Collections.unmodifiableMap(contributions);
  }
}

At this point, the Mapcollection is created, and the last step is to inject the object.

  • Object injectioninjectZoo(Zoo instance)
final class DaggerZooComponent implements ZooComponent {
    
    
   private Zoo injectZoo(Zoo instance) {
    
    
     // 为Zoo对象中的字段赋值在这里
     Zoo_MembersInjector.injectMap(instance, getMapOfClassOfAndAnimal());
     return instance;
   } 
}
public final class Zoo_MembersInjector implements MembersInjector<Zoo> {
    
    
    public static void injectMap(Zoo instance, Map<Class<? extends Animal>, Animal> map) {
    
    
      // 最终的赋值操作.  
      instance.map = map;
    }
}

Guess you like

Origin blog.csdn.net/MoLiao2046/article/details/106890273