Usamos una función de fábrica de Bean para permitir la inyección de objetos Logger en nuestros Beans. Esto se parece a lo que describe Simar Paul Singh en su artículo " Inyectar registradores en primavera "
import org.slf4j.* import org.springframework.beans.factory.InjectionPoint import org.springframework.context.annotation.* @Bean @Scope("prototype") fun logger(injectionPoint: InjectionPoint): Logger { return LoggerFactory.getLogger( injectionPoint.methodParameter?.containingClass // constructor ?: injectionPoint.field?.declaringClass // or field injection ) } Hoy intenté convertir esta declaración en una declaración de Bean usando la definición de bean funcional DSL de Springs . Sin embargo, no logré obtener el InjectionPoint utilizado para recuperar la clase en la que se inyecta el registrador.
import org.slf4j.* import org.springframework.beans.factory.InjectionPoint import org.springframework.context.support.beans import org.springframework.context.support.BeanDefinitionDsl.Scope.PROTOTYPE fun beans() = beans { bean(scope = PROTOTYPE) { val injectionPoint = ref<InjectionPoint>() LoggerFactory.getLogger( injectionPoint.methodParameter?.containingClass // constructor ?: injectionPoint.field?.declaringClass // or field injection ) } }Lo anterior da como resultado una excepción en la línea de:
NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.beans.factory.InjectionPoint' available ¿Hay alguna forma de recuperar el punto de InjectionPoint o al menos la clase para proporcionar un comportamiento similar a la declaración de Bean sin DSL?
Se puede encontrar un repositorio de reproducción mínima en GitHub . Ejecute ./gradlew bootRun o .\gradlew.bat bootRun en Windows para reproducir el error.
Abrí el número 27738 en el repositorio de GitHub de Spring.
No creo que obtenga una instancia de InjectionPoint porque se crea en respuesta a la demanda que hace un componente para una inyección de un bean administrado.
La clase InjectionPoint no está anotada con @Component o cualquiera de sus derivados como @Service . Por lo tanto, no es un bean administrado y no obtendrá una referencia usando ref<InjectionPoint> .
InjectionPoint solo contiene metainformación sobre la clase o el método que solicita una instancia del bean administrado. Es decir, no es un objeto funcional y, por tanto, no gestionado. Sin embargo, el método de fábrica de beans puede aceptarlo opcionalmente para tomar algunas decisiones sobre la instancia que se va a devolver. Por lo tanto, su método de fábrica de frijoles (como se llame en Kotlin) debe aceptar una instancia de InjectionPoint , que es lo que está haciendo en su primera versión en la publicación.
Además, por lo mínimo que pude entender de los documentos de Kotlin Bean DSL aquí , no pude ver una manera de aceptarlo como un parámetro (pero eso podría deberse simplemente a mi falta de conocimiento de Kotlin. Entonces, en resumen, esto puede no ser útil para las definiciones de bean donde se necesita un punto de inyección, a menos que pueda revisar los documentos y encontrar una forma en la que me haya perdido.
No soy un experto en Kotlin, pero ¿puedes probar esto?
fun beans() = beans { bean<InjectionPoint>() bean(scope = PROTOTYPE) { val injectionPoint = ref<InjectionPoint>() LoggerFactory.getLogger( injectionPoint.methodParameter?.containingClass // constructor ?: injectionPoint.field?.declaringClass // or field injection ) } }