spring-fu
spring-fu copied to clipboard
I would like to contribute code that supports R2DBC Repositories.
After several weeks of digging, I found the code that worked. I would like to contribute based on this code. originally, I was use the registerBean method, but the compiler could not find a proper overriding method because the compile time type of beanClass was not clear, so I copied the ClassDerivedBeanDefinition code and called registerBeanDefinition. there anything I need to know?
val app = reactiveWebApplication {
dataR2dbc {
enableR2dbcRepositories()
}
reactiveMongodb {
enableMongoRepositories()
}
}
fun DataR2dbcDsl.enableR2dbcRepositories() {
context.registerBean(R2dbcRepositoryFactory::class.java, Supplier {
val operations = context.getBean(R2dbcEntityOperations::class.java)
R2dbcRepositoryFactory(operations)
})
registerReactiveRepositoryFactoryTo(context)
}
fun ReactiveMongoDsl.enableMongoRepositories() {
context.registerBean(ReactiveMongoRepositoryFactory::class.java, Supplier {
val operations = context.getBean(ReactiveMongoOperations::class.java)
ReactiveMongoRepositoryFactory(operations)
})
registerReactiveRepositoryFactoryTo(context)
}
class RepositoryBeanInfo(
val beanName: String,
val beanClass: Class<*>
)
fun registerReactiveRepositoryFactoryTo(context: GenericApplicationContext) {
context.addBeanFactoryPostProcessor { beanFactory ->
val repoBeans = mutableListOf<RepositoryBeanInfo>()
beanFactory.beanNamesIterator.forEach { beanName ->
val type = beanFactory.getType(beanName)
if (type != null && ReactiveCrudRepository::class.java.isAssignableFrom(type)) {
val beanClass = beanFactory.getType(beanName, true)
beanClass?.let { repoBeans.add(RepositoryBeanInfo(beanName, it)) }
}
}
repoBeans.forEach { info ->
val beanName = info.beanName
val beanClass = info.beanClass
val prevBD = context.getBeanDefinition(beanName)
val beanDefinition = ClassDerivedBeanDefinition(beanClass).apply {
instanceSupplier = Supplier {
val factory = context.getBean(ReactiveRepositoryFactorySupport::class.java)
factory.getRepository(beanClass)
}
BeanDefinitionCustomizer { bd ->
bd.scope = prevBD.scope
bd.isLazyInit = prevBD.isLazyInit
bd.isPrimary = prevBD.isPrimary
bd.isAutowireCandidate = prevBD.isAutowireCandidate
bd.initMethodName = prevBD.initMethodName
bd.destroyMethodName = prevBD.destroyMethodName
bd.description = prevBD.description
bd.role = prevBD.role
}.customize(this)
}
context.removeBeanDefinition(beanName)
context.registerBeanDefinition(beanName, beanDefinition)
}
}
}
class ClassDerivedBeanDefinition : RootBeanDefinition {
constructor(beanClass: Class<*>?) : super(beanClass)
constructor(original: ClassDerivedBeanDefinition) : super(original)
override fun getPreferredConstructors(): Array<Constructor<*>>? {
val clazz = beanClass
val primaryCtor = BeanUtils.findPrimaryConstructor(clazz)
if (primaryCtor != null) {
return arrayOf(primaryCtor)
}
val publicCtors = clazz.constructors
return if (publicCtors.isNotEmpty()) {
publicCtors
} else null
}
override fun cloneBeanDefinition(): RootBeanDefinition {
return ClassDerivedBeanDefinition(this)
}
}