上节详细介绍了java版本的自定义注解处理器步骤, kotlin 版本这里只把内容和注意事项给列出
1 annotation
模块
1.1 结构
1.2 代码
package com.example.annotation
//自定义注解
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.SOURCE)
annotation class APTAnnotation(val value: String = "Default Value") // 定义一个属性
// val priority: Int = 1 // 定义一个优先级属性
1.3 Kotlin DSL 配置
plugins {
alias(libs.plugins.jetbrains.kotlin.jvm)
id("java-library")
}
java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
dependencies {
}
2 annotation-process
模块
2.1 结构
2.2 代码
package com.example.annotationprocess.customapt
import com.example.annotation.APTAnnotation
import com.google.auto.service.AutoService
import java.io.IOException
import javax.annotation.processing.AbstractProcessor
import javax.annotation.processing.RoundEnvironment
import javax.annotation.processing.SupportedAnnotationTypes
import javax.annotation.processing.SupportedSourceVersion
import javax.lang.model.SourceVersion
import javax.lang.model.element.Element
import javax.lang.model.element.TypeElement
import javax.tools.Diagnostic
@SupportedAnnotationTypes("com.example.annotation.APTAnnotation")
@SupportedSourceVersion(SourceVersion.RELEASE_17)
@AutoService(javax.annotation.processing.Processor::class)
class APTAnnotationProcessor : AbstractProcessor() {
override fun process(annotations: Set<TypeElement>?, roundEnv: RoundEnvironment): Boolean {
if (annotations.isNullOrEmpty()) return false
for (element in roundEnv.getElementsAnnotatedWith(APTAnnotation::class.java)) {
val annotation = element.getAnnotation(APTAnnotation::class.java)
val value = annotation.value
processingEnv.messager.printMessage(Diagnostic.Kind.NOTE, "Processing ${element.simpleName} with value $value")
// 在这里生成代码或执行其他操作
generateClass(element, value)
}
return true
}
private fun generateClass(element: Element, value: String) {
// 实现代码生成逻辑,例如生成一个Java类
// 使用Filer创建文件并写入内容
// 获取注解
val annotation = element.getAnnotation(APTAnnotation::class.java)
val className = element.simpleName.toString() + "Generated"
val packageName = processingEnv.elementUtils.getPackageOf(element).toString()
// 生成类内容
val content = """package $packageName;
public class $className {
public static void print() {
System.out.println("${annotation.value}");
}
}"""
try {
// 创建Java源文件
val fileObject = processingEnv.filer.createSourceFile("$packageName.$className")
val writer = fileObject.openWriter()
writer.write(content)
writer.close()
} catch (e: IOException) {
println("生成异常: " + e.message)
e.printStackTrace()
}
}
}
2.3 Kotlin DSl 配置
注意这里面需要启用 kapt
plugins {
alias(libs.plugins.jetbrains.kotlin.jvm)
id("java-library")
id("kotlin-kapt")
}
java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
dependencies {
implementation(project(":annotation"))
implementation("javax.annotation:javax.annotation-api:1.3.2")
implementation ("com.google.auto.service:auto-service:1.0.1")
kapt("com.google.auto.service:auto-service:1.0.1")
}
3 app
模块 注意这里区别于之前 java 的版本,该 modle 为 application模块
3.1 结构
3.2 代码
3.2.1 使用注解
//注解参数也必须是编译时常量。你遇到的“An annotation argument must be a compile-time constant”错误表示你试图将一个运行时计算的值作为注解参数
const val CONSTANT_VALUE = "Hello, custom APT!"
//以常量的形式这样调用注解,否则会报上面那个错误
@APTAnnotation(CONSTANT_VALUE)
class MyClass {
}
3.2.2 编译
kapt
是Kotlin时代的产物,会检索kotlin/java代码,但kotlin的一些专有属性拿不到,如const
关键字、伴生对象等在代码层面无法判断,同样的,没有用到注解时,不会工作;生成的代码在build/generated/source/kapt
目录下
3.2.3 调用编译结果
package com.example.kotlin.other.annotation
//测试注解处理器编译结果
class Test {
}
fun main() {
MyClassGenerated().print()
}
3.3 Kotlin DSl 配置
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.jetbrains.kotlin.android)
id("kotlin-kapt")
}
android {
namespace = "com.example.kotlin"
compileSdk = 34
defaultConfig {
applicationId = "com.example.kotlin"
minSdk = 24
targetSdk = 34
versionCode = 1
versionName = "1.0"
vectorDrawables {
useSupportLibrary = true
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = "17"
}
buildFeatures {
viewBinding = true
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
packaging {
resources {
// excludes += "/META-INF/{AL2.0,LGPL2.1}"
}
}
}
dependencies {
//---
// 编译时注解
implementation(project(":annotation"))
kapt (project(":annotation_process"))
}