kotlin+Spring Bootを使っているとお世話になる「kotlin-spring」が何をやっているかが分からなかったので調査。
早速見てみます。これは@Controllerアノテーション付き。
「public open fun index(…」 とあります。openを明示してないのにopenになってますね。
こっちは@Controllerアノテーションなし。
「public final fun index(…」 になっています。一転、finalになりました。
画像では関数を例にしていますが、アノテーション付きのControllerにもopen
修飾子が付くようになっています。
また、アノテーションが付いてないものはfinalになっています。これはKotlinのデフォルト仕様。
クラスに対してアノテーションを付けるとクラス、変数、関数もopen
修飾子が付きます。
こんな感じでSpringのアノテーションを付けると勝手にをopenにしてくれる設定をどこでやっているかを探ります。
All-open compiler plugin とは?
元はこれ。
https://kotlinlang.org/docs/all-open-plugin.html
前述した通りクラスに対してのアノテーション付与で自動的にopen
修飾子を付けてくれるすごいやつ。
また、Springを使う用途にkotlin-springというコンパイラプラグインが使える。
If you use Spring, you can enable the kotlin-spring compiler plugin instead of specifying Spring annotations manually. The kotlin-spring is a wrapper on top of all-open, and it behaves exactly the same way.
https://kotlinlang.org/docs/all-open-plugin.html#spring-support
これらのアノテーションを使うとopen修飾子が付く
kotlin-spring
を使用して以下のアノテーションを付与した場合、open
になるよ。と書いてある。
The plugin specifies the following annotations:
@Component
@Async
@Transactional
@Cacheable
@SpringBootTest
Thanks to meta-annotations support, classes annotated with
@Configuration
,@Controller
,@RestController
,@Service
or@Repository
are automatically opened since these annotations are meta-annotated with@Component
.
Spring initializr を使ってプロジェクトを作成した場合
build.gradle.kts
の場合こんな記述がデフォルトで存在する。
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile plugins { id("org.springframework.boot") version "2.5.6" id("io.spring.dependency-management") version "1.0.11.RELEASE" kotlin("jvm") version "1.5.31" kotlin("plugin.spring") version "1.5.31" // これ }
kotlin("plugin.spring") version "1.5.31"
の記述があるだけで、前述のアノテーションを付与するだけでopen修飾子が付く設定が完了している。
「all-open」みたいな記述がないので一見適用されていることが分かりづらいがこんな感じ。
他にもGradleでの書き方は色々あるので参考に
https://plugins.gradle.org/plugin/org.jetbrains.kotlin.plugin.spring
メタアノテーションってなんぞや
openにすることが出来るアノテーション一覧で見たこんな記述。
Thanks to meta-annotations support, classes annotated with
@Configuration
,@Controller
,@RestController
,@Service
or@Repository
are automatically opened since these annotations are meta-annotated with@Component
.
要は@Component
使わなくても@Service
とか@RestController
でもopenにすることが出来るよ!という話。
これを実現しているのはメタアノテーションのおかげ、と書いてあるが果たしてなんだろうか。
メタアノテーション = アノテーションに指定出来るアノテーション
メタアノテーションはアノテーションに指定出来るアノテーションのこと。
Springは複数のアノテーションを組み合わせた独自カスタムアノテーションを多く実装している。
@Component
Componentアノテーションには @Targetと@Retention、@Documented、@Indexdのアノテーションが付与されている。
この複数の組み合わせによってComponentアノテーションが作られている。
@Controller
一見別物のように見えるControllerアノテーションには@Component
のアノテーションが付与されている。
ここでは紹介しないが、@Service
、@Repository
、@Configuration
なども同様に@Component
アノテーションが付与されている。
@RestController
一方、RestControllerを見てみる。
@Controllerアノテーションと@ResponseBodyがあるのがわかる。
なるほどなるほど、すべては繋がっている。
@AliasFor でパラメータも渡せる
上記の記述を見ると@AliasFor
でアノテーションクラスを指定しているが、この記述でvalueパラメータも引数のannotationで指定してあげることでアノテーションに値を引き渡す事が出来る。まさにエイリアス。
使い方に関してはこの記事が詳しく書かれてました。
Springのアノテーションを合成してプロジェクト固有のステレオタイプを作る / @kuinaein
アノテーションの組み合わせ夢が広がる
と、言うわけでopen修飾子を付与する事が出来るアノテーションは下記の通りですが、
@Component
@Async
@Transactional
@Cacheable
@SpringBootTest
メタアノテーションの機能を使って@Configuration
, @Controller
, @RestController
, @Service
, @Repository
を使った場合でも、open修飾子が付与されるということです。
環境
- Kotlin v1.5.31
- Spring Boot 2.6.0
参考
Kotlin Compiler Plugin (kotlin-allopen) を追いかける / らびたろちゃんにっき
Springのアノテーションを合成してプロジェクト固有のステレオタイプを作る / @kuinaein
org.jetbrains.kotlin.plugin.spring / gradle
https://www.intertech.com/spring-4-meta-annotations / INTERTECH Spring 4 Meta Annotations
コメント