0%

构建编译AutoService解析

使用


build.gradle

1
implementation 'com.google.auto.service:auto-service:1.0-rc7' //

ITest.java

1
2
3
public interface ITest {
void print();
}

Test.java

1
2
3
4
5
6
7
8
@AutoService(ITest.class)
public class Test implements ITest {

@Override
public void print() {
Log.d("song", "hahaha");
}
}

调用

1
ServiceLoader.load(ITest.class).iterator().next().print();

输出
image.png

apk/META-INF
image.png

原理


ServiceLoader

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
public final class ServiceLoader<S>
implements Iterable<S>
{

private static final String PREFIX = "META-INF/services/";

public static <S> ServiceLoader<S> load(Class<S> service,
ClassLoader loader)
{
return new ServiceLoader<>(service, loader); //实例化一个ServiceLoader
}

public void reload() {
providers.clear(); //缓存作用
lookupIterator = new LazyIterator(service, loader);
}

private ServiceLoader(Class<S> svc, ClassLoader cl) {
service = Objects.requireNonNull(svc, "Service interface cannot be null");
loader = (cl == null) ? ClassLoader.getSystemClassLoader() : cl;
reload();
}

private class LazyIterator
implements Iterator<S>
{


private boolean hasNextService() {
if (nextName != null) {
return true;
}
if (configs == null) {
try {
// META-INF/services/com.leo.events.cardcontrol.ITest
String fullName = PREFIX + service.getName();
if (loader == null)
configs = ClassLoader.getSystemResources(fullName);
else
configs = loader.getResources(fullName);
} catch (IOException x) {
fail(service, "Error locating configuration files", x);
}
}
while ((pending == null) || !pending.hasNext()) {
if (!configs.hasMoreElements()) {
return false;
}
pending = parse(service, configs.nextElement());
}
nextName = pending.next();
return true;
}
}

private Iterator<String> parse(Class<?> service, URL u)
throws ServiceConfigurationError
{
InputStream in = null;
BufferedReader r = null;
ArrayList<String> names = new ArrayList<>();
try {
in = u.openStream();
r = new BufferedReader(new InputStreamReader(in, "utf-8"));
int lc = 1;
while ((lc = parseLine(service, u, r, lc, names)) >= 0);
} catch (IOException x) {
fail(service, "Error reading configuration file", x);
} finally {
try {
if (r != null) r.close();
if (in != null) in.close();
} catch (IOException y) {
fail(service, "Error closing configuration file", y);
}
}
return names.iterator();
}

}

通过ClassLoader的_getSystemResources或者_getResources获取META-INF/services/com.leo.events.cardcontrol.ITest文件,然后在通过parse方法进行解析ITest文件内容,然后再通过解析出的com.leo.events.cardcontrol.Test内容进行反射初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
private S nextService() {
if (!hasNextService())
throw new NoSuchElementException();
String cn = nextName;
nextName = null;
Class<?> c = null;
try {
c = Class.forName(cn, false, loader); // 获取class
} catch (ClassNotFoundException x) {

}
if (!service.isAssignableFrom(c)) {

ClassCastException cce = new ClassCastException(
service.getCanonicalName() + " is not assignable from " + c.getCanonicalName());
}
try {
S p = service.cast(c.newInstance()); //实例化
providers.put(cn, p);
return p;
} catch (Throwable x) {
fail(service,
"Provider " + cn + " could not be instantiated",
x);
}
throw new Error(); // This cannot happen
}

image.png

AutoService

1
2
3
4
5
6
7
8
9
10
11
12
13
|------------------------------------------------------------------------
| javaPreCompileDebug , poseidon|
|------------------------------------------------------------------------
| com.android.build.gradle.tasks.JavaPreCompileTask_Decorated
|------------------------------------------------------------------------
| inputs file|
|-----------------------------------------------------------------
| 没有inputs路径
|-----------------------------------------------------------------
| outputs file|
|-----------------------------------------------------------------
| /Users/juneleo/demo/CardControl/poseidon/build/intermediates/annotation_processor_list/debug/annotationProcessors.json
|-----------------------------------------------------------------

在compileDebugJavaWithJavac之前执行javaPreCompileDebug,这个任务会输出annotationProcessors.json

1
2
3
4
5
6
{
"bundle_apt-1.1.3.jar (com.autonavi.scm:bundle_apt:1.1.3)": false,
"aui-annotation-0.0.7.jar (com.autonavi.aui-annotation:aui-annotation:0.0.7)": false,
"hostkeep.jar (project :hostkeep)": false,
"auto-service-1.0-rc7.jar (com.google.auto.service:auto-service:1.0-rc7)": true
}

在这个json中指定了使用annotationProcessor依赖的项目

JavaPreCompileTask

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62

abstract class JavaPreCompileWorkAction : ProfileAwareWorkAction<JavaPreCompileParameters>() {

override fun run() {
//获取 META-INF/services/javax.annotation.processing.Processor 的依赖
val annotationProcessors =
detectAnnotationProcessors(
parameters.annotationProcessorClassNames.get(),
parameters.annotationProcessorArtifacts.get()
)
//输出到CardControl/app/build/intermediates/annotation_processor_list/debug/annotationProcessors.json
writeAnnotationProcessorsToJsonFile(
annotationProcessors, parameters.annotationProcessorListFile.get().asFile
)
}
}


const val ANNOTATION_PROCESSORS_INDICATOR_FILE =
"META-INF/services/javax.annotation.processing.Processor"
const val INCREMENTAL_ANNOTATION_PROCESSORS_INDICATOR_FILE =
"META-INF/gradle/incremental.annotation.processors"

fun detectAnnotationProcessors(
artifacts: Collection<SerializableArtifact>
): Map<SerializableArtifact, Boolean> {
// TODO We assume that an artifact has an annotation processor if it contains
// ANNOTATION_PROCESSORS_INDICATOR_FILE, and the processor is incremental if it contains
// INCREMENTAL_ANNOTATION_PROCESSORS_INDICATOR_FILE. We need to revisit this assumption as the
// processors may register as incremental dynamically.
val processors = mutableMapOf<SerializableArtifact, Boolean>()

for (artifact in artifacts) {
val artifactFile = artifact.file
// 文件夹
if (artifactFile.isDirectory) {
if (File(artifactFile, ANNOTATION_PROCESSORS_INDICATOR_FILE).exists()) {
processors[artifact] =
File(artifactFile, INCREMENTAL_ANNOTATION_PROCESSORS_INDICATOR_FILE)
.exists()
}

} else if (artifactFile.isFile) { //文件 一般都是jar包
try {
JarFile(artifactFile).use { jarFile ->
//如果包含 META-INF/services/javax.annotation.processing.Processor
if (jarFile.getJarEntry(ANNOTATION_PROCESSORS_INDICATOR_FILE) != null) {
processors[artifact] = jarFile.getJarEntry(
INCREMENTAL_ANNOTATION_PROCESSORS_INDICATOR_FILE
) != null
}
}
} catch (e: IOException) {
// Can happen when we encounter a folder instead of a jar; for instance, in
// sub-modules. We're just displaying a warning, so there's no need to stop the
// build here. See http://issuetracker.google.com/64283041.
}
}
}

return processors
}

META-INF/services/javax.annotation.processing.Processor文件
image.png
image.png

输出路径
image.png

JavaCompile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|------------------------------------------------------------------------
| compileDebugJavaWithJavac , app|
|------------------------------------------------------------------------
| org.gradle.api.tasks.compile.JavaCompile_Decorated
|------------------------------------------------------------------------
| inputs file|
|-----------------------------------------------------------------
| /Users/juneleo/demo/CardControl/app/build/intermediates/annotation_processor_list/debug/annotationProcessors.json
| //省略jar包和java文件
|-----------------------------------------------------------------
| outputs file|
|-----------------------------------------------------------------
| /Users/juneleo/demo/CardControl/app/build/generated/ap_generated_sources/debug/out
| /Users/juneleo/demo/CardControl/app/build/intermediates/javac/debug/classes
|-----------------------------------------------------------------

从图中我们可以看到JavaPreCompileTask的输出作为了JavaCompile的输入

annotationprocess调用链
javacompiler.png

JavaCompile调用jdk入口

1
2
3
4
5
6
7
8
9
10
11
12
13
public Result doCall() {
if (!this.used.getAndSet(true)) {
this.initContext();
this.notYetEntered = new HashMap();
this.compilerMain.setAPIMode(true);
//最后一个参数为annotationProcessor相关
this.result = this.compilerMain.compile(this.args, this.classNames, this.context, this.fileObjects, this.processors);
this.cleanup();
return this.result;
} else {
throw new IllegalStateException("multiple calls to method 'call'");
}
}

args参数
image.png

processor参数
image.png

总结

1.AutoService注解只是为了让编译器能找到Processor类
2.JavaCompiler(可以认为是javac)compile之前会进行会进行processAnnotations生成类
3.JavaCompiler 并没有调用javac,而是调用内部方法循环调用generate生成每一个class
4.JavaCompile是任务compileDebugJavaWithJavac,JavaCompiler是jdk中的class生成器