1.新建Java Library-- 命名为annotation, 新建注解ARouter
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.CLASS)
public @interface ARouter {
String path();
String group() default "";
}
2.新建注解处理器Java Library 命名为compiler, 用来编译时生成代码。
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Filer;
import javax.annotation.processing.Messager;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedOptions;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;
import javax.tools.Diagnostic;
@AutoService(Processor.class)
@SupportedAnnotationTypes({"com.XXX.annotation.ARouter"})
@SupportedSourceVersion(SourceVersion.RELEASE_7)
@SupportedOptions("maValue")
public class ArouterProcesser extends AbstractProcessor {
private Elements mElementsTool;
private Types mTypesTool;
private Messager messager;
private Filer mFiler;
@Override
public synchronized void init(ProcessingEnvironment processingEnvironment) {
super.init(processingEnvironment);
mElementsTool = processingEnvironment.getElementUtils();
mTypesTool = processingEnvironment.getTypeUtils();
messager = processingEnvironment.getMessager();
mFiler = processingEnvironment.getFiler();
String value = processingEnvironment.getOptions().get("maValue");
messager.printMessage(Diagnostic.Kind.NOTE,"------------->" + value);
}
@Override
public boolean process(Set extends TypeElement> set, RoundEnvironment roundEnvironment) {
if(set.isEmpty()){
messager.printMessage(Diagnostic.Kind.NOTE,"没有发现 被@ARouter注解的地方呀" + set.size());
return false;
}
Set extends Element> elements = roundEnvironment.getElementsAnnotatedWith(ARouter.class);
for(Element element:elements){
//包名
String packageName = mElementsTool.getPackageOf(element).getQualifiedName().toString();
//类名
String className = element.getSimpleName().toString();
messager.printMessage(Diagnostic.Kind.NOTE,"被注解的类名>>>>>" + className);
ARouter aRouter = element.getAnnotation(ARouter.class);
/**
* package com.example.helloworld;
*
* public final class HelloWorld {
* public static void main(String[] args) {
* System.out.println("Hello, JavaPoet!");
* }
* }
*/
// MethodSpec methodSpec = MethodSpec.methodBuilder("main")
// .addModifiers(Modifier.PUBLIC,Modifier.STATIC)
// .returns(void.class)
// .addParameter(String[].class,"args")
// .addStatement("$T.out.println($S)",System.class,"hello world")
// .build();
//
// TypeSpec typeSpec = TypeSpec.classBuilder("HelloWorld")
// .addModifiers(Modifier.PUBLIC,Modifier.FINAL)
// .addMethod(methodSpec)
// .build();
//
// JavaFile javaFile = JavaFile.builder("com.example.helloworld",typeSpec)
// .build();
//
// try {
// javaFile.writeTo(mFiler);
// } catch (IOException e) {
// e.printStackTrace();
// messager.printMessage(Diagnostic.Kind.ERROR,"failed to create....");
// }
// =====================================================
/**
* public class MainActivity$$$$$$$$$ARouter {
* public static Class findTargetClass(String path) {
* return path.equals("app/MainActivity") ? MainActivity.class : null;
* }
* }
*/
MethodSpec methodSpec = MethodSpec.methodBuilder("findTargetClass")
.addModifiers(Modifier.PUBLIC,Modifier.STATIC)
.returns(Class.class)
.addParameter(String.class,"path")
.addStatement("return path.equals($S) ? $T.class : null",aRouter.path(), ClassName.get((TypeElement) element))
.build();
String finalClsName = className + "$$ARouter";
TypeSpec typeSpec = TypeSpec.classBuilder(finalClsName)
.addModifiers(Modifier.PUBLIC)
.addMethod(methodSpec)
.build();
JavaFile javaFile = JavaFile.builder(packageName,typeSpec).build();
try {
javaFile.writeTo(mFiler);
} catch (IOException e) {
e.printStackTrace();
}
}
return true;
}
}
build.gradle代码:
apply plugin: 'java-library'
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
// 构建 -------》 【编译时期.....】 ------》打包 ----》安装
// AS3.4.1 + Gradle 5.1.1 + auto-service:1.0-rc4
compileOnly'com.google.auto.service:auto-service:1.0-rc4'
annotationProcessor'com.google.auto.service:auto-service:1.0-rc4'
implementation project(':annotation')
implementation "com.squareup:javapoet:1.9.0"
}
tasks.withType(JavaCompile){
options.encoding="UTF-8"
}
sourceCompatibility = "7"
targetCompatibility = "7"
3.在主Moudle app的MainActivity加上注解@ARouter
@ARouter(path = "/app/MainActivity")
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
主module app的build.gradle
apply plugin: 'com.android.application'
android {
compileSdkVersion 29
buildToolsVersion "29.0.3"
defaultConfig {
applicationId "com.XXX.majavapoet"
minSdkVersion 21
targetSdkVersion 29
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
javaCompileOptions{
annotationProcessorOptions{
//给注解传入参数
arguments = [maValue:'hello Javapoet'];
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
//依赖注解
implementation project(":annotation")
//依赖注解处理器
annotationProcessor project(":compiler")
}