ButterKnife依赖注入框架源码解析
创始人
2024-02-06 13:01:47
0

BuffterKnife 采用 注解+ APT技术
APT:Annotation Processor tool 注解处理器,是javac的一个工具,每个处理器都是继承于AbstractProcessor

注解处理器是运行在自己的java虚拟机中

APT如何生成字节码文件:
在这里插入图片描述

Annotation Processing 不能加入或删除java方法

APT整个流程

    1. 声明的注解等待生命周期为CLASS
    1. 继承AbstractProcessor类
    1. 再调用AbstractProcessor 的process方法

AbstractProcessor.java

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package javax.annotation.processing;import java.util.Collections;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic.Kind;public abstract class AbstractProcessor implements Processor {protected ProcessingEnvironment processingEnv;private boolean initialized = false;protected AbstractProcessor() {}public Set getSupportedOptions() {SupportedOptions so = (SupportedOptions)this.getClass().getAnnotation(SupportedOptions.class);return so == null ? Collections.emptySet() : arrayToSet(so.value(), false);}public Set getSupportedAnnotationTypes() {  // 返回所支持注解的类型SupportedAnnotationTypes sat = (SupportedAnnotationTypes)this.getClass().getAnnotation(SupportedAnnotationTypes.class);boolean initialized = this.isInitialized();if (sat == null) {if (initialized) {this.processingEnv.getMessager().printMessage(Kind.WARNING, "No SupportedAnnotationTypes annotation found on " + this.getClass().getName() + ", returning an empty set.");}return Collections.emptySet();} else {boolean stripModulePrefixes = initialized && this.processingEnv.getSourceVersion().compareTo(SourceVersion.RELEASE_8) <= 0;return arrayToSet(sat.value(), stripModulePrefixes);}}public SourceVersion getSupportedSourceVersion() {  //用来指定所使用的java版本SupportedSourceVersion ssv = (SupportedSourceVersion)this.getClass().getAnnotation(SupportedSourceVersion.class);SourceVersion sv = null;if (ssv == null) {sv = SourceVersion.RELEASE_6;if (this.isInitialized()) {Messager var10000 = this.processingEnv.getMessager();Kind var10001 = Kind.WARNING;String var10002 = this.getClass().getName();var10000.printMessage(var10001, "No SupportedSourceVersion annotation found on " + var10002 + ", returning " + sv + ".");}} else {sv = ssv.value();}return sv;}public synchronized void init(ProcessingEnvironment processingEnv) {  // 初始化工作if (this.initialized) {throw new IllegalStateException("Cannot call init more than once.");} else {Objects.requireNonNull(processingEnv, "Tool provided null ProcessingEnvironment");this.processingEnv = processingEnv;this.initialized = true;}}public abstract boolean process(Set var1, RoundEnvironment var2);  // process相对于main函数,即方法的入口,在process方法中可以完成扫描、评估、处理注解等等代码。process方法最后会生成所需要的java代码public Iterable getCompletions(Element element, AnnotationMirror annotation, ExecutableElement member, String userText) {return Collections.emptyList();}protected synchronized boolean isInitialized() {return this.initialized;}private static Set arrayToSet(String[] array, boolean stripModulePrefixes) {assert array != null;Set set = new HashSet(array.length);String[] var3 = array;int var4 = array.length;for(int var5 = 0; var5 < var4; ++var5) {String s = var3[var5];if (stripModulePrefixes) {int index = s.indexOf(47);if (index != -1) {s = s.substring(index + 1);}}set.add(s);}return Collections.unmodifiableSet(set);}
}

ProcessingEnvironment.java

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package javax.annotation.processing;import java.util.Locale;
import java.util.Map;
import javax.lang.model.SourceVersion;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;public interface ProcessingEnvironment {Map getOptions();Messager getMessager();Filer getFiler();  //用于创建文件Elements getElementUtils();  //用来处理Element的工具类,Element是指在注解处理过程中扫描的所有java源文件,可以把这个源文件想象成Element的全部,而源代码中每个独立的部分就可以认作为特定类型的ElementTypes getTypeUtils();  //TypeElement代表Element的类型, Types是用于获取源代码类型的信息SourceVersion getSourceVersion();Locale getLocale();
}

ButterKnife的工作原理

  1. 编译的时候扫描注解,并做相应的处理,生成java代码,生成Java代码是调用 javapoet 库生成的
  2. 调用ButterKnife.bind(this);方法的时候,将ID与对应的上下文绑定在一起

相关内容

热门资讯

原央视主持人赵普呼吁北大关心韦... 极目新闻记者 陈洋洋 近日,北京大学数学科学学院研究员韦东奕开通个人账号的消息引发广泛关注。视频当中...
SNH48成员周诗雨发长文宣布... 搜狐娱乐讯 7日,SNH48成员周诗雨发长文宣布与丝芭解约,结束长达七年的合作关系。她称自己没有受到...
“超越日本,中国首次跃居首位” 据《日本经济新闻》网站6月4日报道,中国在氢相关专利竞争力方面超越日本,首次跃居首位。中国企业主要在...
菏泽一高考考生午休躺在路边休息... 6月7日,全国高考。山东菏泽,有网友拍到暖心一幕,中午高考午休时间,一名考生躺在路边休息,旁边的家人...
海关律师、走私辩护律师邵丹:查... 近日,海口海关所属海口美兰机场海关联合海口海关风控分局,发现海口飞往遵义的3名旅客购物时间趋近、购物...
海关律师、走私辩护律师邵丹:查... 近日,哈尔滨海关所属哈尔滨太平机场海关关员在对进境航班实施监管时,发现1名选择“无申报通道”入境的旅...
中国女排3比0击败法国女排,斩... 北京时间6月7日晚,中国女排再度亮相世界女排联赛中国北京站,与法国女排展开对抗。 最终,中国女排以3...
《政务数据共享条例》来了,哪些... 《政务数据共享条例》近日正式出台,目的是推进政务数据安全有序高效共享利用,提升政府数字化治理能力和政...
对华新招?美国被曝暂停向中国出... 【文/观察者网 齐倩】在中美贸易紧张关系持续之际,路透社6月6日援引消息称,特朗普政府近日暂停了美国...
欧洲央行执委Schnabel:... 欧洲央行执委Isabel Schnabel称,对美联储与欧洲央行政策将长期分化的预期是错误的。“我预...