From d98326b7bfd18c812a0cf2b4a029910e157b66f9 Mon Sep 17 00:00:00 2001 From: IlyaMuravjov Date: Mon, 24 Apr 2023 13:55:27 +0300 Subject: [PATCH] Rewrite findBeanClassNames in UtBotBeanFactoryPostProcessor --- .../UtBotBeanFactoryPostProcessor.kt | 36 +++++++++++++++---- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/utbot-spring-analyzer/src/main/kotlin/org/utbot/spring/postProcessors/UtBotBeanFactoryPostProcessor.kt b/utbot-spring-analyzer/src/main/kotlin/org/utbot/spring/postProcessors/UtBotBeanFactoryPostProcessor.kt index a8a604581b..e351253d2f 100644 --- a/utbot-spring-analyzer/src/main/kotlin/org/utbot/spring/postProcessors/UtBotBeanFactoryPostProcessor.kt +++ b/utbot-spring-analyzer/src/main/kotlin/org/utbot/spring/postProcessors/UtBotBeanFactoryPostProcessor.kt @@ -4,6 +4,7 @@ import com.jetbrains.rd.util.getLogger import com.jetbrains.rd.util.info import com.jetbrains.rd.util.warn import org.springframework.beans.factory.BeanCreationException +import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition import org.springframework.beans.factory.config.BeanFactoryPostProcessor import org.springframework.beans.factory.config.ConfigurableListableBeanFactory import org.springframework.beans.factory.support.BeanDefinitionRegistry @@ -30,16 +31,37 @@ object UtBotBeanFactoryPostProcessor : BeanFactoryPostProcessor, PriorityOrdered throw UtBotSpringShutdownException("Finished post-processing bean factory in UtBot", beanQualifiedNames) } - private fun findBeanClassNames(beanFactory: ConfigurableListableBeanFactory): List { - return beanFactory.beanDefinitionNames.mapNotNull { - try { - beanFactory.getBeanDefinition(it).beanClassName ?: beanFactory.getBean(it).javaClass.name + private fun findBeanClassNames(beanFactory: ConfigurableListableBeanFactory): List = + beanFactory.beanDefinitionNames + .mapNotNull { getBeanFqn(beanFactory, it) } + .filterNot { it.startsWith("org.utbot.spring") } + .distinct() + + private fun getBeanFqn(beanFactory: ConfigurableListableBeanFactory, beanName: String): String? { + val beanDefinition = beanFactory.getBeanDefinition(beanName) + return if (beanDefinition is AnnotatedBeanDefinition) { + if (beanDefinition.factoryMethodMetadata == null) { + // there's no factoryMethod so bean is defined with @Component-like annotation rather than @Bean annotation + // same approach isn't applicable for @Bean beans, because for them, it returns name of @Configuration class + beanDefinition.metadata.className.also { fqn -> + logger.info { "Got $fqn as metadata.className for @Component-like bean: $beanName" } + } + } else try { + // TODO to avoid side effects, determine beanClassName without getting bean by analyzing method + // defining bean, for example, by finding all its return statements and determining their common type + // NOTE: do not simply use return type from method signature because it may be an interface type + beanFactory.getBean(beanName)::class.java.name.also { fqn -> + logger.info { "Got $fqn as runtime type for @Bean-like bean: $beanName" } + } } catch (e: BeanCreationException) { - logger.warn { "Failed to get bean: $it" } + logger.warn { "Failed to get bean: $beanName" } null } - }.filterNot { it.startsWith("org.utbot.spring") } - .distinct() + } else { + beanDefinition.beanClassName.also { fqn -> + logger.info { "Got $fqn as beanClassName for XML-like bean: $beanName" } + } + } } private fun destroyBeanDefinitions(beanFactory: ConfigurableListableBeanFactory) {