@@ -4,6 +4,7 @@ import com.jetbrains.rd.util.getLogger
44import com.jetbrains.rd.util.info
55import com.jetbrains.rd.util.warn
66import org.springframework.beans.factory.BeanCreationException
7+ import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition
78import org.springframework.beans.factory.config.BeanFactoryPostProcessor
89import org.springframework.beans.factory.config.ConfigurableListableBeanFactory
910import org.springframework.beans.factory.support.BeanDefinitionRegistry
@@ -30,16 +31,37 @@ object UtBotBeanFactoryPostProcessor : BeanFactoryPostProcessor, PriorityOrdered
3031 throw UtBotSpringShutdownException (" Finished post-processing bean factory in UtBot" , beanQualifiedNames)
3132 }
3233
33- private fun findBeanClassNames (beanFactory : ConfigurableListableBeanFactory ): List <String > {
34- return beanFactory.beanDefinitionNames.mapNotNull {
35- try {
36- beanFactory.getBeanDefinition(it).beanClassName ? : beanFactory.getBean(it).javaClass.name
34+ private fun findBeanClassNames (beanFactory : ConfigurableListableBeanFactory ): List <String > =
35+ beanFactory.beanDefinitionNames
36+ .mapNotNull { getBeanFqn(beanFactory, it) }
37+ .filterNot { it.startsWith(" org.utbot.spring" ) }
38+ .distinct()
39+
40+ private fun getBeanFqn (beanFactory : ConfigurableListableBeanFactory , beanName : String ): String? {
41+ val beanDefinition = beanFactory.getBeanDefinition(beanName)
42+ return if (beanDefinition is AnnotatedBeanDefinition ) {
43+ if (beanDefinition.factoryMethodMetadata == null ) {
44+ // there's no factoryMethod so bean is defined with @Component-like annotation rather than @Bean annotation
45+ // same approach isn't applicable for @Bean beans, because for them, it returns name of @Configuration class
46+ beanDefinition.metadata.className.also { fqn ->
47+ logger.info { " Got $fqn as metadata.className for @Component-like bean: $beanName " }
48+ }
49+ } else try {
50+ // TODO to avoid side effects, determine beanClassName without getting bean by analyzing method
51+ // defining bean, for example, by finding all its return statements and determining their common type
52+ // NOTE: do not simply use return type from method signature because it may be an interface type
53+ beanFactory.getBean(beanName)::class .java.name.also { fqn ->
54+ logger.info { " Got $fqn as runtime type for @Bean-like bean: $beanName " }
55+ }
3756 } catch (e: BeanCreationException ) {
38- logger.warn { " Failed to get bean: $it " }
57+ logger.warn { " Failed to get bean: $beanName " }
3958 null
4059 }
41- }.filterNot { it.startsWith(" org.utbot.spring" ) }
42- .distinct()
60+ } else {
61+ beanDefinition.beanClassName.also { fqn ->
62+ logger.info { " Got $fqn as beanClassName for XML-like bean: $beanName " }
63+ }
64+ }
4365 }
4466
4567 private fun destroyBeanDefinitions (beanFactory : ConfigurableListableBeanFactory ) {
0 commit comments