ksp注解处理器基本使用

ksp注解处理器基本使用

引入依赖

新建一个项目,在项目build.gradle中引入依赖:

	dependencies {
        classpath 'com.google.devtools.ksp:com.google.devtools.ksp.gradle.plugin:1.6.21-1.0.6'
    }

编写注解

新建一个模块,编写想要处理多注解
这个模块的build.gradle只需要简单配置为一个java-library就行,例如:

plugins {
    id 'java-library'
    id 'kotlin'
}

java {
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
}

接下来新建文件编写注解,注解编写方法可参考官方文档
例如这样:

@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.SOURCE)
annotation class Hello()

注解处理

新建一个模块,用作注解处理

  • build.gradle基础配置
plugins {
    id 'java-library'
    id 'kotlin'
}

java {
    sourceCompatibility = JavaVersion.VERSION_1_8
    targetCompatibility = JavaVersion.VERSION_1_8
}

  • 依赖配置
    首先需要引入依赖库,其中 'com.google.devtools.ksp:symbol-processing-api:1.6.21-1.0.6'是必须的,"com.squareup:kotlinpoet:1.12.0"'com.squareup:kotlinpoet-ksp:1.12.0'可选,这两个库可以使处理符号生成文件更方便

    implementation 'com.google.devtools.ksp:symbol-processing-api:1.6.21-1.0.6'
    implementation "com.squareup:kotlinpoet:1.12.0"
    implementation 'com.squareup:kotlinpoet-ksp:1.12.0'

接下来引入编写的注解模块
例如:

implementation(project(":hello"))
  • 实现SymbolProcessor
    新建一个类继承自com.google.devtools.ksp.processing.SymbolProcessor,实现
    process方法,在方法中获取所有被注解的符号依次处理,符号处理使用ksp,具体参考ksp官方文档
    例如:
class HelloProcessor(private val environment: SymbolProcessorEnvironment): SymbolProcessor {
    override fun process(resolver: Resolver): List<KSAnnotated> {
        resolver.getSymbolsWithAnnotation(Hello::class.java.name).forEach {
            if (it is KSFunctionDeclaration && it.containingFile != null) {
                FileSpec.builder(packageName = it.packageName.asString(), "Hello")
                    .addType(TypeSpec.classBuilder("Hello").build())
                    .addFunction(FunSpec.builder("hello")
                        .addModifiers(KModifier.PRIVATE)
                        .addStatement("println(\"hello\")")
                        .build()
                    )
                    .build()
                    .writeTo(environment.codeGenerator, Dependencies(false, it.containingFile!!))
            }
        }
        return emptyList()
    }
}
  • 实现SymbolProcessorProvider
    新建一个类继承自com.google.devtools.ksp.processing.SymbolProcessorProvider,实现create方法,返回刚才实现的SymbolProcessor类的实例
    例如:

class HelloProvider: SymbolProcessorProvider {
    override fun create(environment: SymbolProcessorEnvironment): SymbolProcessor {
        return HelloProcessor(environment)
    }
}
  • 入口配置
    在注解处理器模块main下新建一个resources资源包,继续在resources下新建META-INF包,继续,在META-INF下新建一个gradle包,在gradle下新建一个文件,文件名称为incremental.annotation.processors,此文件内容为刚才实现的SymbolProcessor类的全名;接下来在META-INF下再新建一个services包,包下新建文件,文件名为com.google.devtools.ksp.processing.SymbolProcessorProvider,文件内容为刚才实现的SymbolProcessorProvider类的全名。

最终目录结构如下:
目录结构

新建一个模块使用它

新建一个模块

  • 引入注解模块:
    implementation(project(":hello"))

  • 引入注解处理器ksp插件
    id 'com.google.devtools.ksp'

  • 引入自己实现的注解处理模块
    ksp(project(":hello-compiler"))

  • 在此模块中新建一个文件使用这个注解
    例如:
	@Hello
    fun test() {
        println("test")
    }
  • 编译,会发现在build目录中已生成新的文件,如下:
    生成的文件示例
    至此,成功!!

补充一些内容:

我们使用注解生成的文件后续肯定是要引用的,为了能在项目其他文件中引用,我们需要在gradle文件(当然也可能是kts文件,以下一gradle文件为例)中配置sourceSet来包含生成文件所在的目录,例如只希望debug引用我们可以这样配置:


kotlin {
    sourceSets.debug {
        kotlin.srcDir("build/generated/ksp/debug/kotlin")
    }
}

如果还希望release也可以访问,我们可以再添加这样的配置:

    sourceSets.release {
        kotlin.srcDir("build/generated/ksp/release/kotlin")
    }
<think>好的,用户问的是纯Java项目是否可以使用KSPKotlin Symbol Processing)来生成代码。首先,我需要确认KSP基本特性和使用环境。KSPKotlin的符号处理工具,主要用于在编译阶段处理Kotlin代码,生成新的代码或资源。通常,KSPKotlin项目结合使用,因为它依赖于Kotlin的编译器和符号处理API。 接下来,用户提到的是纯Java项目。这里需要考虑Java项目是否能够集成KSP。由于KSP本身是为Kotlin设计的,它的API和插件机制都是围绕Kotlin编译器构建的。Java项目虽然可以通过Kotlin混合项目的方式间接使用Kotlin代码,但纯Java项目可能无法直接利用KSP,因为KSP需要处理的是Kotlin的符号,而Java的符号处理机制不同。 然后,我需要思考是否有变通方法。例如,是否可以在Java项目中添加Kotlin的依赖,并配置KSP插件。理论上,如果项目允许引入Kotlin编译插件,可能可以配置KSP来处理Kotlin代码,即使主代码是Java。但这样就不再是“纯”Java项目了,变成了混合项目。此外,生成的代码如果是Kotlin的,可能还需要确保Java代码能够正确调用这些生成的Kotlin类,可能需要处理互操作性问题。 另外,用户可能需要了解替代方案。如果纯Java项目无法使用KSP,可以考虑其他Java注解处理器,如APT(Annotation Processing Tool),这是Java原生的代码生成工具,广泛用于生成代码,比如Lombok库。APT在Java生态中成熟且稳定,适合纯Java项目。 还需要验证一些技术细节,比如KSP是否只能在Kotlin源代码上运行,或者是否能处理Java代码。根据官方文档,KSP主要处理Kotlin代码,对Java的支持有限。因此,如果项目中没有Kotlin文件,KSP可能无法发挥作用。 最后,总结回答时需要明确说明纯Java项目无法直接使用KSP,但可以通过引入Kotlin依赖和配置来间接使用,同时建议考虑Java原生的APT作为替代方案。这样用户可以根据项目需求选择合适的方法。</think>### 纯 Java 项目能否使用 KSP 生成代码? #### 1. **KSP基本特性** Kotlin Symbol Processing(KSP)是 Kotlin 的符号处理工具,主要用于在编译时分析 Kotlin 代码并生成新代码。它的核心依赖是 **Kotlin 编译器**,设计目标是为 Kotlin 代码提供比传统注解处理器(如 Java APT)更高效、更准确的符号处理。 #### 2. **纯 Java 项目的限制** - **语言依赖**:KSP 直接处理的是 Kotlin 的符号(如 Kotlin 类、函数、属性),**无法直接解析 Java 代码**。如果项目中只有 Java 代码,KSP 无法获取有效输入。 - **编译环境**:KSP 需要 Kotlin 编译器插件支持,而纯 Java 项目通常不包含 Kotlin 编译环境。即使手动添加 Kotlin 依赖,仍需混合 Kotlin 代码才能触发 KSP。 #### 3. **变通方案(非纯 Java)** 若允许项目中引入 Kotlin,可通过以下步骤间接使用 KSP: 1. **添加 Kotlin 依赖**: ```gradle plugins { id "org.jetbrains.kotlin.jvm" version "1.9.0" // 最低需要 Kotlin 1.4.0 } ``` 2. **配置 KSP 插件**: ```gradle plugins { id "com.google.devtools.ksp" version "1.9.0-1.0.13" } ``` 3. **编写 KSP 处理器**(需用 Kotlin 实现): ```kotlin class ExampleProcessor : SymbolProcessor { override fun process(resolver: Resolver) { // 处理 Kotlin 符号并生成代码 } } ``` 4. **生成的代码需兼容 Java**:生成的 Kotlin 类需添加 `@JvmStatic` 等注解,确保 Java 能调用。 #### 4. **纯 Java 项目的替代方案** - **Java 注解处理器(APT)**: - 使用 `javax.annotation.processing` 实现,支持纯 Java 项目。 - 示例工具:Lombok、MapStruct、Google Auto 等。 - 配置简单,无需 Kotlin 依赖。 - **字节码操作库**(如 ASM、Byte Buddy): - 在编译后直接修改字节码,但需熟悉 JVM 指令。 #### 5. **对比总结** | 方案 | 适用语言 | 复杂度 | 生成阶段 | 典型工具 | |---------------|------------|--------|---------------|------------------| | KSP | Kotlin | 中 | 编译时(Kotlin) | KSP 插件 | | Java APT | Java | 低 | 编译时(Java) | Lombok, Auto | | 字节码操作 | 任何 JVM 语言 | 高 | 编译后 | ASM, Byte Buddy | #### 6. **结论** - **纯 Java 项目无法直接使用 KSP**,因为 KSP 依赖 Kotlin 编译器和符号。 - **替代方案**: - 如果允许引入 Kotlin,可通过混合编程间接使用 KSP。 - 如果坚持纯 Java,优先选择 Java APT 或字节码操作库。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值