Skip to content

Commit b9830f5

Browse files
committed
完善代码
1 parent 65fa1b7 commit b9830f5

File tree

17 files changed

+886
-1
lines changed

17 files changed

+886
-1
lines changed

.idea/jarRepositories.xml

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/modules.xml

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/runConfigurations.xml

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package com.yc.api.compiler;
2+
3+
import java.util.Collections;
4+
import java.util.Iterator;
5+
import java.util.LinkedHashSet;
6+
import java.util.ServiceConfigurationError;
7+
import java.util.Set;
8+
9+
public final class ServiceLoader<S> implements Iterable<S> {
10+
11+
public static <S> ServiceLoader<S> load(final Class<S> serviceClass) {
12+
return new ServiceLoader<S>(serviceClass);
13+
}
14+
15+
private final Class<S> mService;
16+
17+
private final Set<S> mProviders = new LinkedHashSet<S>();
18+
19+
private ServiceLoader(final Class<S> service) {
20+
this.mService = service;
21+
this.load();
22+
}
23+
24+
public S get() {
25+
final Iterator<S> i = this.mProviders.iterator();
26+
if (i.hasNext()) {
27+
return i.next();
28+
}
29+
30+
return null;
31+
}
32+
33+
@Override
34+
public Iterator<S> iterator() {
35+
return Collections.unmodifiableSet(this.mProviders).iterator();
36+
}
37+
38+
private void load() {
39+
for (final Class<? extends S> provider : ServiceRegistry.get(this.mService)) {
40+
try {
41+
final S p = ServiceRegistry.newProvider(provider);
42+
this.mProviders.add(p);
43+
} catch (final Throwable t) {
44+
throw new ServiceConfigurationError("Provider " + provider.getName() + " could not be initialized", t);
45+
}
46+
}
47+
}
48+
49+
}
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
package com.yc.api.compiler;
2+
3+
import com.google.auto.service.AutoService;
4+
import com.squareup.javapoet.ClassName;
5+
import com.squareup.javapoet.FieldSpec;
6+
import com.squareup.javapoet.JavaFile;
7+
import com.squareup.javapoet.MethodSpec;
8+
import com.squareup.javapoet.TypeName;
9+
import com.squareup.javapoet.TypeSpec;
10+
import com.yc.api.ServiceProviderInterface;
11+
12+
import java.io.IOException;
13+
import java.util.Collections;
14+
import java.util.List;
15+
import java.util.Set;
16+
17+
import javax.annotation.processing.AbstractProcessor;
18+
import javax.annotation.processing.ProcessingEnvironment;
19+
import javax.annotation.processing.Processor;
20+
import javax.annotation.processing.RoundEnvironment;
21+
import javax.lang.model.SourceVersion;
22+
import javax.lang.model.element.Element;
23+
import javax.lang.model.element.ExecutableElement;
24+
import javax.lang.model.element.Modifier;
25+
import javax.lang.model.element.TypeElement;
26+
import javax.lang.model.element.VariableElement;
27+
import javax.lang.model.type.TypeMirror;
28+
import javax.lang.model.util.ElementFilter;
29+
import javax.lang.model.util.Elements;
30+
31+
32+
@AutoService(Processor.class)
33+
public class ServiceProviderInterfaceProcessor extends AbstractProcessor {
34+
35+
private Elements utils;
36+
37+
@Override
38+
public Set<String> getSupportedAnnotationTypes() {
39+
return Collections.singleton(ServiceProviderInterface.class.getCanonicalName());
40+
}
41+
42+
@Override
43+
public SourceVersion getSupportedSourceVersion() {
44+
return SourceVersion.RELEASE_7;
45+
}
46+
47+
@Override
48+
public synchronized void init(final ProcessingEnvironment processingEnv) {
49+
super.init(processingEnv);
50+
this.utils = processingEnv.getElementUtils();
51+
}
52+
53+
@Override
54+
public boolean process(final Set<? extends TypeElement> annotations, final RoundEnvironment roundEnv) {
55+
for (final Element element : roundEnv.getElementsAnnotatedWith(ServiceProviderInterface.class)) {
56+
if (element instanceof TypeElement) {
57+
final TypeElement typeElement = (TypeElement) element;
58+
final String packageName = getPackageName(typeElement);
59+
final ClassName clazzSpi = ClassName.get(typeElement);
60+
final ClassName clazzLoader = ClassName.get(getClass().getPackage().getName(), "ServiceLoader");
61+
final ClassName clazzService = ClassName.get(packageName, getServiceName(typeElement));
62+
final ClassName clazzSingleton = ClassName.get(packageName, clazzService.simpleName(), "Singleton");
63+
final TypeSpec.Builder tsb = TypeSpec.classBuilder(clazzService)
64+
.addJavadoc("Represents the service of {@link $T}\n", clazzSpi)
65+
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
66+
.addSuperinterface(clazzSpi)
67+
.addType(TypeSpec.classBuilder(clazzSingleton.simpleName())
68+
.addModifiers(Modifier.PRIVATE, Modifier.STATIC, Modifier.FINAL)
69+
.addField(FieldSpec.builder(clazzService, "INSTANCE", Modifier.STATIC, Modifier.FINAL)
70+
.initializer("new $T()", clazzService)
71+
.build())
72+
.build())
73+
.addField(FieldSpec.builder(clazzSpi, "mDelegate", Modifier.PRIVATE, Modifier.FINAL)
74+
.initializer("$T.load($T.class).get()", clazzLoader, clazzSpi)
75+
.build())
76+
.addMethod(MethodSpec.constructorBuilder()
77+
.addModifiers(Modifier.PRIVATE)
78+
.build())
79+
.addMethod(MethodSpec.methodBuilder("getInstance")
80+
.addModifiers(Modifier.PUBLIC, Modifier.STATIC, Modifier.FINAL)
81+
.addStatement("return $T.INSTANCE", clazzSingleton)
82+
.returns(clazzService)
83+
.build());
84+
85+
System.out.println("Generate " + clazzService.toString());
86+
87+
for (final ExecutableElement method : ElementFilter.methodsIn(typeElement.getEnclosedElements())) {
88+
System.out.println(" + " + method);
89+
final String methodName = method.getSimpleName().toString();
90+
final TypeMirror returnType = method.getReturnType();
91+
final MethodSpec.Builder msb = MethodSpec.methodBuilder(methodName)
92+
.addModifiers(Modifier.PUBLIC, Modifier.FINAL)
93+
.addAnnotation(Override.class)
94+
.returns(TypeName.get(returnType));
95+
96+
for (final TypeMirror thrownType : method.getThrownTypes()) {
97+
msb.addException(ClassName.get(thrownType));
98+
}
99+
100+
final StringBuilder args = new StringBuilder();
101+
final List<? extends VariableElement> parameterTypes = method.getParameters();
102+
for (int i = 0, n = parameterTypes.size(); i < n; i++) {
103+
final String argName = "arg" + i;
104+
msb.addParameter(TypeName.get(parameterTypes.get(i).asType()), argName, Modifier.FINAL);
105+
args.append(argName).append(i < n - 1 ? ", " : "");
106+
}
107+
108+
switch (returnType.getKind()) {
109+
case BOOLEAN:
110+
msb.addStatement("return null != this.mDelegate && this.mDelegate.$L($L)", methodName, args);
111+
break;
112+
case BYTE:
113+
msb.addStatement("return null != this.mDelegate ? this.mDelegate.$L($L) : (byte) 0", methodName, args);
114+
break;
115+
case SHORT:
116+
msb.addStatement("return null != this.mDelegate ? this.mDelegate.$L($L) : (short) 0", methodName, args);
117+
break;
118+
case INT:
119+
case FLOAT:
120+
case LONG:
121+
case DOUBLE:
122+
msb.addStatement("return null != this.mDelegate ? this.mDelegate.$L($L) : 0", methodName, args);
123+
break;
124+
case CHAR:
125+
msb.addStatement("return null != this.mDelegate ? this.mDelegate.$L($L) : '\0'", methodName, args);
126+
break;
127+
case VOID:
128+
msb.beginControlFlow("if (null != this.mDelegate)")
129+
.addStatement("this.mDelegate.$L($L)", methodName, args)
130+
.endControlFlow();
131+
break;
132+
default:
133+
msb.addStatement("return null != this.mDelegate ? this.mDelegate.$L($L) : null", methodName, args);
134+
break;
135+
}
136+
137+
tsb.addMethod(msb.build());
138+
}
139+
140+
try {
141+
JavaFile.builder(getPackageName(typeElement), tsb.build())
142+
.indent(" ")
143+
.addFileComment("\nAutomatically generated file. DO NOT MODIFY\n")
144+
.skipJavaLangImports(true)
145+
.build()
146+
.writeTo(processingEnv.getFiler());
147+
} catch (final IOException e) {
148+
e.printStackTrace();
149+
}
150+
}
151+
}
152+
153+
return true;
154+
}
155+
156+
private String getServiceName(final TypeElement typeElement) {
157+
final String simpleName = typeElement.getSimpleName().toString();
158+
if (simpleName.endsWith("ServiceProvider")) {
159+
return simpleName.substring(0, simpleName.length() - 8);
160+
}
161+
162+
return simpleName + "Service";
163+
}
164+
165+
private String getPackageName(final TypeElement typeElement) {
166+
return this.utils.getPackageOf(typeElement).getQualifiedName().toString();
167+
}
168+
169+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.yc.api.compiler;
2+
3+
import java.util.Set;
4+
5+
6+
public abstract class ServiceRegistry {
7+
8+
private ServiceRegistry() {
9+
10+
}
11+
12+
public static synchronized <S, P extends S> void register(final Class<S> serviceClass, final Class<P> providerClass) {
13+
throw new RuntimeException("Stub!");
14+
}
15+
16+
public static synchronized <S> Set<Class<? extends S>> get(final Class<S> clazz) {
17+
throw new RuntimeException("Stub!");
18+
}
19+
20+
static synchronized <S> S newProvider(final Class<? extends S> clazz) {
21+
throw new RuntimeException("Stub!");
22+
}
23+
24+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package com.yc.api;
2+
3+
import java.lang.annotation.ElementType;
4+
import java.lang.annotation.Retention;
5+
import java.lang.annotation.RetentionPolicy;
6+
import java.lang.annotation.Target;
7+
8+
@Target(ElementType.TYPE)
9+
@Retention(RetentionPolicy.RUNTIME)
10+
public @interface ServiceProvider {
11+
12+
/**
13+
* Returns provided interfaces
14+
*/
15+
Class<?>[] value();
16+
17+
/**
18+
* Returns the priority
19+
*/
20+
int priority() default 0;
21+
22+
/**
23+
* Returns the alias
24+
*/
25+
String alias() default "";
26+
27+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.yc.api;
2+
3+
import java.lang.annotation.ElementType;
4+
import java.lang.annotation.Retention;
5+
import java.lang.annotation.RetentionPolicy;
6+
import java.lang.annotation.Target;
7+
8+
@Target(ElementType.TYPE)
9+
@Retention(RetentionPolicy.RUNTIME)
10+
public @interface ServiceProviderInterface {
11+
}

api-plugin/build.gradle

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
buildscript {
2+
repositories {
3+
mavenLocal()
4+
mavenCentral()
5+
jcenter()
6+
}
7+
}
8+
9+
apply plugin: 'java'
10+
apply plugin: 'groovy'
11+
apply plugin: 'maven'
12+
13+
sourceCompatibility = "1.8"
14+
targetCompatibility = "1.8"
15+
16+
repositories {
17+
mavenLocal()
18+
mavenCentral()
19+
jcenter()
20+
}
21+
22+
dependencies {
23+
implementation gradleApi()
24+
implementation localGroovy()
25+
implementation 'org.javassist:javassist:3.18.2-GA'
26+
implementation 'com.squareup:javapoet:1.7.0'
27+
implementation project(path: ':api-compiler')
28+
implementation project(path: ':api-manager')
29+
}
30+

api-plugin/gradle.properties

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
org.gradle.daemon=true
2+
org.gradle.jvmargs=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005
3+

0 commit comments

Comments
 (0)