Gradle自定义ArchUnit插件无法扫描客户端项目类的问题求助
问题分析与解决方案
核心问题
你的插件当前存在两个关键问题:
- 使用
Test类型任务完全没必要,反而会混淆类加载环境——doLast块是在插件自身的类加载器中执行的,ArchUnit只能扫描到插件JAR里的类,根本看不到子项目编译后的类文件。 - ArchUnit的包扫描逻辑依赖当前类加载器,没有指定从子项目的编译输出目录加载类。
修改后的插件代码
class ArchUnitPlugin : Plugin<Project> { override fun apply(project: Project) { val runArchUnitTests = project.tasks.register("runArchUnitTests", DefaultTask::class.java) { group = "verification" description = "Runs ArchUnit tests" val sourceSets = project.extensions.getByType<SourceSetContainer>() val main = sourceSets.getByName("main") // 确保先完成源码编译,拿到最新的class文件 dependsOn(main.compileJavaTaskName) // 告诉Gradle任务输入是子项目的编译输出目录,支持增量构建 inputs.dir(main.output.classesDirs) outputs.upToDateWhen { true } doLast { // 把子项目的class目录传递给校验器 ServiceAnnotationVerifier().verifyServiceAnnotations(main.output.classesDirs.files) } } // 保留依赖test任务的配置(如果需要) runArchUnitTests.configure { dependsOn("test") } } }
修改后的规则代码
class ServiceAnnotationVerifier { fun verifyServiceAnnotations(classDirs: Collection<File>) { // 直接从子项目的编译输出目录导入类文件,而非依赖插件类加载器 val importedClasses = ClassFileImporter() .importLocations(*classDirs.toTypedArray()) val servicesShouldBeAnnotatedWithService = ArchRuleDefinition.classes() .that() .resideInAPackage("..service..") .and() .haveSimpleNameNotEndingWith("Test") .should() .beAnnotatedWith(Service::class.java) .orShould() .beAnnotatedWith(Component::class.java) .because("Need to ensure that all service classes are annotated with @Service") // 可选:如果允许子项目没有service包的情况,取消下面注释 // servicesShouldBeAnnotatedWithService.allowEmptyShould(true) servicesShouldBeAnnotatedWithService.check(importedClasses) } }
关键修改说明
- 切换任务类型:改用
DefaultTask替代Test任务,避免Test框架的类路径干扰,简化执行环境。 - 绑定编译任务:通过
dependsOn(main.compileJavaTaskName)确保检查前子项目代码已编译完成。 - 明确类源路径:直接传递子项目的
classesDirs给ArchUnit,让它扫描目标项目的类文件,而非插件自身的类。 - 支持增量构建:通过
inputs.dir标记任务输入,Gradle会自动跳过未修改类的重复检查。
额外注意事项
- 如果子项目同时用Java和Kotlin编译,
main.output.classesDirs会自动包含两种语言的编译输出目录,无需额外处理。 - 若需要扫描子项目依赖中的类,可以把
main.runtimeClasspath也加入importLocations,但通常ArchUnit检查仅关注项目自身代码。 - 若部分子项目可能没有
service包,添加allowEmptyShould(true)到规则中,避免无匹配类时触发报错。
内容的提问来源于stack exchange,提问作者Codex
相关产品推荐
相关产品推荐

