We use a Bean factory function to allow injection of Logger objects into our Beans. This looks similar to what Simar Paul Singh describes in his article "Inject loggers in Spring"
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
)
}
Today I attempted to convert this declaration into a Bean declaration using Springs functional bean definition DSL. However I did not succeed to get a hold of the InjectionPoint
used to retrieve the class the Logger is injected into.
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
)
}
}
The above results in an exception along the lines of:
NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.beans.factory.InjectionPoint' available
Is there a way to retrieve the InjectionPoint
or at least the class to provide a behaviour similar to the Bean declaration without DSL?
A minimal reproduction repository can be found on GitHub.
Run ./gradlew bootRun
or .\gradlew.bat bootRun
on Windows to reproduce the error.
I've opened issue #27738 on the GitHub repository of Spring.
I don't think you will get an instance of InjectionPoint
because it is created in response to the demand a component makes for an injection of a managed bean.
InjectionPoint
class is not annotated with @Component
or any of its derivatives like @Service
. Hence, it is not a managed bean and you will not get a reference using ref<InjectionPoint>
.
InjectionPoint
only contains meta information about the class or method that is requesting an instance of the managed bean. That is, it not a functional object and hence, not managed. However, it can be optionally accepted by the bean factory method to make some decisions about the instance to be returned. Hence, your bean factory method (whatever it is called in Kotlin) must accept an instance of InjectionPoint
, which is what you are doing in your first version in the post.
Also, from the minimal I could understand from the docs of Kotlin Bean DSL here, I couldn't see a way to accept it as a parameter (but that could simply be due to my lack of knowledge of Kotlin. So, in summary, this may not be useful for bean definitions where injection point is needed, unless you can go through the docs and find out a way which I may have missed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With