ARouter 依赖注入实现原理
- 这里只是记录一下ARouter中的依赖注入的源码实现方式,对于ARouter的其他分析,比如路由等,将会在后面的博客中进行分享。
1.首先我们知道要进行依赖注入的话,得先添加一个注解比如
@Autowired
String name;
@Autowired
int age;
2.然后我们在看看这个注解的定义:
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.CLASS)
public @interface Autowired {
// Mark param's name or service name.
String name() default "";
// If required, app will be crash when value is null.
// Primitive type wont be check!
boolean required() default false;
// Description of the field
String desc() default "No desc.";
}
在这里 有两个属性值得我们关注 就是name和required (第三个是 description的,已经废弃了)
name属性就是给它一个别名 比如
@Autowired(name = "boy")
boolean girl;
在传值的时候就可以用别名来传递了
required属性表示进行null判断,如果是iProvider的子类 且 为null 则抛出异常,如果不是iProvider的子类 为null的话 只是打印一句话。
- 既然有了注解,那么就肯定有注解处理器啦,下面看看这个注解处理器(注解处理器这里面会自动生成文件)。我们一段一段来看
首先:
@AutoService(Processor.class)
@SupportedOptions(KEY_MODULE_NAME)
@SupportedSourceVersion(SourceVersion.RELEASE_7)
@SupportedAnnotationTypes({ANNOTATION_TYPE_AUTOWIRED})
public class AutowiredProcessor extends AbstractProcessor {
private Filer mFiler; // File util, write class file into disk.
private Logger logger;
private Types types;
private TypeUtils typeUtils;
private Elements elements;
private Map<TypeElement, List<Element>> parentAndChild = new HashMap<>(); // Contain field need autowired and his super class.
private static final ClassName ARouterClass = ClassName.get("com.alibaba.android.arouter.launcher", "ARouter");
private static final ClassName AndroidLog = ClassName.get("android.util", "Log");
@Override
public synchronized void init(ProcessingEnvironment processingEnvironment) {
super.init(processingEnvironment);
mFiler = processingEnv.getFiler(); // Generate class.
types = processingEnv.getTypeUtils(); // Get type utils.
elements = processingEnv.getElementUtils(); // Get class meta.
typeUtils = new TypeUtils(types, elements);
logger = new Logger(processingEnv.getMessager()); // Package the log utils.
logger.info(">>> AutowiredProcessor init. <<<");
}
}
这一段代码中,我们最需要知道的一点就是parentAndChild,这个容器装了当前类中所有的需要依赖注入的字段(这段就比较水了,哈哈哈)。
接下来看到这段代码:
@Override
public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
if (CollectionUtils.isNotEmpty(set)) {
try {
logger.info(">>> Found autowired field, start... <<<");
categories(roundEnvironment.getElementsAnnotatedWith(Autowired.class));
generateHelper();
} catch (Exception e) {
logger.error(e);
}
return true;
}
return false;
}
这段代码中会调用2个方法
categories(roundEnvironment.getElementsAnnotatedWith(Aut