** kapt 目前逐渐被淘汰了,这节介绍 ksp 版本**
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 代码
注意这里和之前的定义不太一样,这里的自定义注解处理器实现了SymbolProcessorProvider,生成逻辑是一致的,大家可以做对比,这个需要依赖另外一个库,同时开启 ksp
package com.example.annotationprocess.apt
import com.example.annotation.APTAnnotation
import com.google.devtools.ksp.processing.CodeGenerator
import com.google.devtools.ksp.processing.Dependencies
import com.google.devtools.ksp.processing.KSPLogger
import com.google.devtools.ksp.processing.Resolver
import com.google.devtools.ksp.processing.SymbolProcessor
import com.google.devtools.ksp.processing.SymbolProcessorEnvironment
import com.google.devtools.ksp.processing.SymbolProcessorProvider
import com.google.devtools.ksp.symbol.KSAnnotated
import com.google.devtools.ksp.symbol.KSClassDeclaration
import com.squareup.kotlinpoet.FileSpec
import com.squareup.kotlinpoet.FunSpec
import com.squareup.kotlinpoet.TypeSpec
import java.io.OutputStreamWriter
import javax.annotation.processing.Processor
//@AutoService(SymbolProcessorProvider::class)
class MyAnnotationProcessorProvider : SymbolProcessorProvider {
override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor {
return MyAnnotationProcessor(environment.codeGenerator, environment.logger)
}
}
class MyAnnotationProcessor(
private val codeGenerator: CodeGenerator,
private val logger: KSPLogger
) : SymbolProcessor {
override fun process(resolver: Resolver): List<KSAnnotated> {
val symbols = resolver.getSymbolsWithAnnotation(APTAnnotation::class.qualifiedName!!)
symbols.filterIsInstance<KSClassDeclaration>().forEach { classDeclaration ->
val className = "${classDeclaration.simpleName.asString()}Generated"
val fileSpec = FileSpec.builder(
packageName = classDeclaration.packageName.asString(),
fileName = className
).addType(
TypeSpec.classBuilder(className)
.addFunction(
FunSpec.builder("print")
.addStatement("println("Generated by MyAnnotationProcessor with value: ")")
.build()
)
.build()
).build()
codeGenerator.createNewFile(
dependencies = Dependencies.ALL_FILES,
packageName = classDeclaration.packageName.asString(),
fileName = className
).writer().use { writer ->
fileSpec.writeTo(writer)
}
logger.info("Generated file for ${classDeclaration.simpleName.asString()}")
}
return emptyList()
}
}
2.3 Kotlin DSL 配置
注意这里面不用 autoservice 注册的话不需要启用 ksp
plugins {
alias(libs.plugins.jetbrains.kotlin.jvm)
// id("java-library")
// id("com.google.devtools.ksp") version "1.9.24-1.0.20"
}
java {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
dependencies {
implementation(project(":annotation"))
// 添加 kotlinpoet 依赖
implementation("com.squareup:kotlinpoet:1.12.0")
implementation ("com.google.devtools.ksp:symbol-processing-api:1.9.24-1.0.20")
// ksp("com.google.devtools.ksp:symbol-processing-api:1.9.24-1.0.20")
// implementation ("com.google.auto.service:auto-service:1.0.1")
// ksp("com.google.auto.service:auto-service:1.0.1")
}
2.4 手动注册
这里面我用了 autoservice 一直报错,暂时无法解决 所以用了手动注册的方式,创建如下路径的文件
文件内容如下
com.example.annotationprocess.apt.MyAnnotationProcessorProvider
3 app模块 注意这里区别于之前 java 的版本,该 modle 为 application模块
3.1 结构
3.2 代码
3.2.1 使用注解
package com.example.kotlin.other.annotation
import com.example.annotation.APTAnnotation
//注解参数也必须是编译时常量。你遇到的“An annotation argument must be a compile-time constant”错误表示你试图将一个运行时计算的值作为注解参数
const val CONSTANT_VALUE = "Hello, custom APT!"
//以常量的形式这样调用注解,否则会报上面那个错误
@APTAnnotation(CONSTANT_VALUE)
class MyClass {
}
3.2.2 编译
注意:- ksp则是最新的注解处理器,编译速度号称是kapt的2倍有余,且完全弥补了kapt/annotationProcessor的缺陷,但纯Java项目用不了,必需要集成kotlin;生成的代码在build/generated/ksp目录下
3.2.3 调用编译结果
package com.example.kotlin.other.annotation
//测试注解处理器编译结果
class Test {
}
fun main() {
MyClassGenerated().print()
}
3.3 Kotlin DSl 配置
import com.android.build.gradle.AppExtension
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.jetbrains.kotlin.android)
id("com.google.devtools.ksp") version "1.9.24-1.0.20"
}
//extensions.getByType<AppExtension>().apply {
// applicationVariants.all {
// addJavaSourceFoldersToModel(file("$buildDir/generated/ksp/$name/kotlin"))
// }
//}
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"))
ksp (project(":annotation_process"))
}