You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取Kotlin Spring Boot项目中方法级@Foo注解的所有biz属性值

解决方案

完全可以实现,下面给出两种Spring Boot项目中最常用的实现方案:

方案1:基于Spring上下文扫描(推荐)

该方案仅扫描Spring托管的Bean中的方法,无需引入额外依赖,准确率和性能最优。

前置要求

首先确保你的@Foo注解配置了运行时保留策略,否则运行期无法读取注解信息:

@Target(AnnotationTarget.FUNCTION)
@Retention(AnnotationRetention.RUNTIME) // 必须加这个配置
annotation class Foo(val biz: String)

实现代码

你可以写一个配置类在Spring上下文初始化完成后执行扫描:

import org.springframework.context.ApplicationContext
import org.springframework.context.annotation.Configuration
import org.springframework.context.event.ContextRefreshedEvent
import org.springframework.context.event.EventListener

@Configuration
class FooAnnotationScanner(
    private val applicationContext: ApplicationContext
) {
    // 存储所有扫描到的biz值
    val fooBizList = mutableListOf<String>()

    @EventListener(ContextRefreshedEvent::class)
    fun scanFooAnnotations() {
        // 拿到Spring上下文所有的Bean实例
        val allBeans = applicationContext.getBeansOfType(Any::class.java).values
        allBeans.forEach { bean ->
            // 遍历Bean的所有声明方法
            bean::class.java.declaredMethods.forEach { method ->
                // 提取带@Foo注解的biz属性
                method.getAnnotation(Foo::class.java)?.let { fooAnnotation ->
                    fooBizList.add(fooAnnotation.biz)
                }
            }
        }
    }
}

之后你可以在任意需要的地方注入FooAnnotationScanner,直接取fooBizList属性即可拿到所有取值。

方案2:全类路径扫描

如果需要扫描非Spring托管的类中的@Foo注解,可以使用Spring自带的类路径扫描工具实现:

import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider
import org.springframework.core.type.filter.AnnotationTypeFilter
import org.springframework.core.type.classreading.MetadataReader

fun scanAllFooBiz(basePackage: String): List<String> {
    val bizList = mutableListOf<String>()
    val scanner = object : ClassPathScanningCandidateComponentProvider(false) {
        override fun isCandidateComponent(metadataReader: MetadataReader): Boolean = true
    }
    // 过滤出包含@Foo注解方法的类
    scanner.addIncludeFilter { metadataReader, _ ->
        metadataReader.annotationMetadata.hasAnnotatedMethods(Foo::class.java.name)
    }
    // 扫描指定包下的所有类
    val components = scanner.findCandidateComponents(basePackage)
    val classLoader = Thread.currentThread().contextClassLoader
    components.forEach { beanDefinition ->
        val clazz = classLoader.loadClass(beanDefinition.beanClassName)
        clazz.declaredMethods.forEach { method ->
            method.getAnnotation(Foo::class.java)?.let {
                bizList.add(it.biz)
            }
        }
    }
    return bizList
}

调用时传入你需要扫描的项目根包路径即可,比如scanAllFooBiz("com.your.project.package")

注意事项

  • 如果需要扫描接口、父类中定义的带@Foo注解的方法,需要给@Foo注解添加@Inherited元注解
  • 方法重载场景下多个同名方法都带@Foo注解的话,所有方法的biz值都会被正常提取

内容的提问来源于stack exchange,提问作者Working Title

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 12:39:03