I want to initialize a repository
object in Spring Boot without having to make it a bean or an Autowired
property.
I just want to do feedRepository = FeedRepository()
in Kotlin. Why won't Spring Boot allow me to do this? Why does it have to be autowired or a bean?
here's my code:
@Component
class UriParser() {
@Autowired
lateinit var uriRepository: UriRepository
@Autowired
lateinit var hostRepository: HostRepository
@Autowired
lateinit var feedRepository: FeedRepository
fun parseUri(uri: String) : Feed {
val urlRepository = UriRepository()
val uri = URI(uri)
val uriRecord = uriRepository.save(Uri(scheme = uri.scheme, host = uri.host, port = uri.port))
hostRepository.save(Host(host = uri.host))
return feedRepository.save(Feed(uriId = uriRecord.id))
}
}
Edit: ok so here's better context as to why I can't autowire things. Basically I'm doing this within a static function so I have absolutely no access to beans or autowired properties:
@SpringBootApplication
class Application
fun main(args: Array<String>) {
runApplication<Application>(*args)
KafkaScheduler().init()
}
The Kafka scheduler basically executes several threads which all listen to kafka topics:
class KafkaScheduler() {
// this doesn't work....
@Autowired
lateinit var feedRepository: FeedRepository
fun init() {
val threads = arrayOf(
{
QueueListener().init()
},
{
PrefetchListener().init()
},
{
FetchListener().init()
}
)
val service = Executors.newFixedThreadPool(threads.size)
for (thread in threads) {
service.submit(thread)
}
}
}
however, I can't autowire the KafkaScheduler class as a bean within a static method so I can't really make that a component or autowire any repositories, as far as I know.
Well I figured it out. A simple @PostConstruct
annotation solves everything I need for this. Essentially, I just mark KafkaScheduler
as a @Component
, autowire everything I need within it, the only difference is I added @PostConstruct
to the init method so I have access to the autowired properties. Then I can autowire the repositories wherever I need them (in this case within QueueListener
which uses UriParser
)
@Component
class KafkaScheduler() {
@Autowired
lateinit var queueListener: QueueListener
@Autowired
lateinit var prefetchListener: PrefetchListener
@Autowired
lateinit var fetchListener: FetchListener
@PostConstruct
fun init() {
val threads = arrayOf(
{
queueListener.init()
},
{
prefetchListener.init()
},
{
fetchListener.init()
}
)
val service = Executors.newFixedThreadPool(threads.size)
for (thread in threads) {
service.submit(thread)
}
}
}
Noone stops you from initializing objects by yourself inside the spring managed component.
However, these objects:
@Autowired
in this case because it works only between spring beans.For example, this is wrong because class A is not managed by spring:
// not managed by spring
class A {
}
@Component
class B {
@Autowired
A a;
}
So I believe you aim for something like this:
@Component
class UriParser() {
// no autowired here, you manage everything by youself
// also possible from constructor
lateinit var uriRepository = UriRepository()
...
}
Side note, I haven't learnt Kotlin, so the syntax might be wrong.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.