Доступ к компонентам, управляемым Spring, за пределами классов, управляемых spring, в котлине

#spring #spring-boot #kotlin

Вопрос:

Мы можем получить доступ к управляемым компонентам spring из класса, который не является управляемым spring, с помощью метода getBean функции ниже. Я хочу сделать то же самое, но в Котлине. Как я могу перезаписать функцию getBeans в Котлине, чтобы она работала?

 @Component
public class SpringContext implements ApplicationContextAware {
    private static ApplicationContext context;

    /**
     * Returns the Spring managed bean instance of the given class type if it exists.
     * Returns null otherwise.
     * @param beanClass
     * @return
     */

    public static <T extends Object> T getBean(Class<T> beanClass) {
        return context.getBean(beanClass);
    }


    @Override
    public void setApplicationContext(ApplicationContext context) throws BeansException {

        // store ApplicationContext reference to access required beans later on
        SpringContext.context = context;
    }
}
 

Я пытался преобразовать его в kotlin, но получаю ошибку.

 @Component
class SpringContext : ApplicationContextAware {
    @Throws(BeansException::class)
    override fun setApplicationContext(context: ApplicationContext) {
        // store ApplicationContext reference to access required beans later on
        SpringContext.Companion.context = context
    }

    companion object {
        private var context: ApplicationContext? = null

        fun <T : Any>getBean(beanClass: KClass<out T>): Any {
            return context!!.getBean(beanClass)
        }
    }
}
 
 org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'java.lang.Object' available: more than one 'primary' bean found among candidates: [org.springframework.context.annotation.internalConfigurationAnnotationProcessor, org.springframework.context.annotation.internalAutowiredAnnotationProcessor, org.springframework.context.annotation.internalCommonAnnotationProcessor, org.springframework.context.annotation.internalPersistenceAnnotationProcessor, org.springframework.context.event.internalEventListenerProcessor, org.springframework.context.event.internalEventListenerFactory....]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.determinePrimaryCandidate(DefaultListableBeanFactory.java:1591)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1188)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveBean(DefaultListableBeanFactory.java:420)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:350)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1133)
 

Каким-то образом переменная beanClass получает java.lang.Объект. Почему это происходит и как я могу это решить?

Ответ №1:

В моем приложении Kotlin создан компонент Spring класса под названием WhiskyCrawler .
У меня есть контекст Spring только в моем main методе, поэтому я могу вызывать getBean только там.
Но поскольку в вашем коде есть контекст Spring, вы можете сосредоточиться на последней строке в следующем фрагменте кода:

     @SpringBootApplication
    class WhiskyApplication

    fun main(args: Array<String>) {
        val context = runApplication<WhiskyApplication>(*args)
        val crawler = context.getBean(WhiskyCrawler::class.java)