Search code examples
springspring-bootkotlinaopfinal

How does Spring make a service class open? I thought Kotlin is final by default


The methods or classes in Kotlin are final by default. But when I mark a method in a Service class to be @Transactional, I realised the service class and all its methods are open. Because for the @Transactional aspect to work, the service class needs to be proxied, then it must be an open class so that the proxy class can extend the original class.

(As the tutorial Open Keyword in Kotlin points out, kotlin is final by default.

According to the Spring documentation AOP, because my service class inherits from an abstract class instead of an interface, so the proxy is a CGLIB proxy.)

Did I misunderstand anything or how does it work?


@Service
class SomeService(...): SomeAbstractClass(...){
    @Transactional
    fun someMethod(...){...}
}

Solution

  • Indeed, Spring automatically configures Service classes, etc to be open.

    Because this is to important to the way Spring and other frameworks work, Kotlin documentation talks about it here: All-open compiler plugin

    Kotlin has classes and their members final by default, which makes it inconvenient to use frameworks and libraries such as Spring AOP that require classes to be open. The all-open compiler plugin adapts Kotlin to the requirements of those frameworks and makes classes annotated with a specific annotation and their members open without the explicit open keyword.

    For instance, when you use Spring, you don't need all the classes to be open, but only classes annotated with specific annotations like @Configuration or @Service. The all-open plugin allows you to specify such annotations.

    Kotlin provides all-open plugin support both for Gradle and Maven with the complete IDE integration.

    For Spring, you can use the kotlin-spring compiler plugin.