如何获取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
相关产品推荐
相关产品推荐

