spring-kotlin-coroutine is a repository that contains several libraries and a demo app which allows using Kotlin coroutines in
Spring applications as first-class citizens.
spring-data-mongodb-kotlin-coroutine - a library which allow using Kotlin coroutines in Spring Data Mongo applications. It contains
support for CoroutineMongoRepository and CoroutineMongoTemplate.
spring-boot-autoconfigure-kotlin-coroutine - a library which contains autoconfiguration support for spring-data-mongodb-kotlin-coroutine
via @EnableCoroutineMongoRepositories annotation.
spring-kotlin-coroutine-demo - contains a sample application which demonstrates the use of spring-kotlin-coroutine and
spring-webmvc-kotlin-coroutine.
This annotation enables using the features described below. If it is possible to use a feature without this annotation
it is explicitly stated so in the feature description. The annotation can be used as follows:
Because coroutines can be suspended and they have an additional implicit callback parameter they cannot be used
as web methods by default. With special parameter and result handling introduced in spring-webmvc-kotlin-coroutine
you can safely use coroutines as web methods. You can e.g. have the following component:
Spring beans and its methods can be annotated with @Coroutine. Using this annotation you can specify
the coroutine context via the context attribute and the coroutine name via the name attribute.
The context specifies a name of a bean from which a CoroutineContext can be created. Currently the following
contexts/bean types are supported:
Using @Coroutine it is quite easy to achieve the same effect as with @Async, although the code will look much simpler:
@RestController
openclassMyController(
privatevalrepository:MyRepository
) {
@GetMapping("/customers")
suspendopenfungetCustomers(): List<Customer> {
return repository.getAllCustomers()
}
}
@Component
@Coroutine(DEFAULT_DISPATCHER)
openclassMyRepository {
suspendopenfungetAllCustomers(): List<Customer> {
// a blocking code// which will be run with DEFAULT_DISPATCHER context// or simply ForkJoinPool...
}
}
Application events
Spring allows you to decouple senders and receivers of application events with the usage of ApplicationEventPublisher and
@EventListener methods. They cannot, however, be coroutines. spring-kotlin-coroutine allows you to send
events in a way that allows the suspension of event processing. You can also have an @EventListener method which is a
coroutine.
For sending a component with the following interface can be used:
Your bean can inject this interface or it can implement a CoroutineApplicationEventPublisherAware interface and have
it delivered via a setCoroutineApplicationEventPublisher method:
if it returns a single value it will be treated as a newly published event
if it returns an array or a collection of values it will be treated as a collection of newly published events
@Cacheable support
Due to an additional callback parameter and a special return value semantics coroutine return values cannot be cached using
default Spring caching feature. However with spring-kotlin-coroutine it is possible to use a @Cacheable annotation
on a coroutine, e.g.:
Coroutines annotated with @Scheduled will
not work with regular Spring. However, with spring-kotlin-coroutine you can use them the same way you would do it with regular methods with the following caveats:
schedulerDispatcher attribute of @EnableCoroutine annotation (if a custom value is specified) - it works the same way as the
context attribute of @Coroutine annotation (see @Coroutine section), or
val restOps =DeferredRestOperations(restOperations =RestTemplate(), start =CoroutineStart.DEFAULT, context =COMMON_POOL)
val defaultRestOps =DeferredRestOperations()
If you do not specify any arguments when creating DeferredRestOperations it will delegate all calls to RestTemplate
instance and use a special coroutine context which will immediately invoke the blocking method of RestTemplate on a separate thread
(just like AsyncRestTemplate). You can specify your own RestOperations and CoroutineContext to change that behaviour.
By changing the start parameter value you can specify when the REST operation should be invoked (see CoroutineStart for details).
By using spring-webflux-kotlin-coroutine module instead of spring-webmvc-kotlin-coroutine web methods which are
suspending functions will use Spring Web Flux. This enables them to use non-blocking I/O API.
CoroutineWebClient
CoroutineWebClient is a counterpart of the Spring Web Flux WebClient component. The differences between these components
can be found mainly in the functions which operate on reactive types - in CoroutineWebClient they are suspending functions
operating on regular types. Also the naming of the methods can be slightly different (e.g. in WebClient you can find bodyToMono
and in CoroutineWebClient it is simply body).
Functional style routes definition
TBD
CoroutineMongoRepository
spring-data-mongodb-kotlin-coroutine contains support for CoroutineMongoRepository-based repositories. These repositories
work as regular Spring Data Mongo or Spring Data Mongo Reactive repositories, but have support for suspending functions
and ReceiveChannel type.
CoroutineMongoTemplate
CoroutineMongoTemplate is a counterpart of regular MongoTemplate, but contains suspending functions instead of regular ones.
EnableCoroutineMongoRepositories
The @EnableCoroutineMongoRepositories annotation works just like @EnableMongoRepositories annotation, but enables
the usage of CoroutineMongoRepository repositories.
ListenableFuture extensions
The kotlinx.coroutines library provides interoperability functions with many existing asynchronous libraries (
RxJava v1, RxJava v2,
CompletableFuture, etc.). However, there is no support for Spring specific ListenableFuture interface. Therefore
spring-kotlin-coroutine provides the following features:
fun <T> listenableFuture(context: CoroutineContext = DefaultDispatcher, block: suspend () -> T): ListenableFuture<T> - it
allows you to create a ListenableFuture from a coroutine with specific coroutine context.
fun <T> Deferred<T>.asListenableFuture(): ListenableFuture<T> - it allows you to create a ListenableFuture from
Kotlin coroutine specific Deferred type.
suspend fun <T> ListenableFuture<T>.await(): T - it allows you to create a coroutine from a ListenableFuture.
Note that these extensions do not need @EnableCoroutine in order to work.
Utility functions
Note that utility functions do not need @EnableCoroutine in order to work.
createCoroutineProxy
createCoroutineProxy can be used to create a smart proxy - an instance of an interface which will delegate all
function invocations to a regular object with matching method signatures. The runtime characteristics of this
proxy call depends on the types of the interface methods, the types of the proxied object methods and
the proxy config. The createCoroutineProxy is declared as follows:
fun <T:Any> createCoroutineProxy(coroutineInterface:Class<T>, obj:Any, proxyConfig:CoroutineProxyConfig): T
Currently supported proxy types are as follows:
Coroutine interface method
Object method
Proxy config
suspend fun m(a: A): T
fun m(a: A): T
DefaultCoroutineProxyConfig
fun <T> m(a: A): Deferred<T>
fun m(a: A): T
DeferredCoroutineProxyConfig
Method.isSuspend
Method.isSuspend allows you to check if a method is a coroutine. It is defined as follows:
valMethod.isSuspend:Boolean
Using in your projects
Note that this library is experimental and is subject to change.
Note that some of the dependencies of spring-kotlin-coroutine are declared as optional. You should declare them as
runtime dependencies of your application if you want to use the features that require them. The table below contains the
details:
And make sure that you use the right Kotlin version:
buildscript {
ext.kotlin_version ='1.3.30'
}
FAQ
Why all the methods/classes have "Coroutine" as part of its name and not "Suspending"?
It's a deliberate choice. In most cases Coroutine just sounded better to me and even though sometimes Suspending
might've been a better choice for consistency Coroutine was used.
License
spring-kotlin-coroutine is released under version 2.0 of the Apache License.
请发表评论