Configuration annotationのproxyBeanMethodsとBean Lite Modeについての備忘録
記事の概略
- SpringのBeanにはBean Lite Modeというものがある
- Spring 5.2から@Componentの代わりに@Configuration(proxyBeanMethods = false)を指定することでBean Lite Modeにできる
- CGLIB Proxyが不要ならパフォーマンスがよくなる
- https://github.com/spring-projects/spring-boot/issues/9068 を読めば大体わかる
以下は自分の勉強の備忘録になります。上のissueが完璧なのであんまり読む価値ない。
@Configuration#proxyBeanMethods
Spring Sleuthのコードを読んでいたら見慣れない@Configurationの書き方を見つけました。
@Configuration(proxyBeanMethods = false)
Spring5.2から追加されたもので、falseを指定することでCGLIB Proxyを利用したAspectJ系の処理が動かなくなります。 Bean Lite Modeと呼ばれるものらしいです。
Bean Lite Mode
初めて聞いた単語だったので、下の解説を読んで少し勉強しました。
Bean (Spring Framework 5.2.3.BUILD-SNAPSHOT API)
@Configuration
の代わりに@Component
を利用することで通常のBeanではなくBean Lite Modeで登録できるようです。
普通のBeanとの違いはCGLIB proxyを利用しないことです。このため inter-bean referencesが利用できなくなります。 (Bean間参照、であっているだろうか)
デモプログラム
BeanとBean Lite Modeの違いを確認するデモを用意しました。
@SpringBootApplication class DemoApplication fun main(args: Array<String>) { runApplication<DemoApplication>(*args) } // ここのアノテーションを切り替えるとBean Lite Modeになる @Configuration // @Component // @Configuration(proxyBeanMethods = false) class FooBarConfiguration { @Bean fun foo(): Foo { val id = UUID.randomUUID().toString() println("create: $id") return Foo(id) } @Bean fun bar(): Bar { println(foo()) return Bar() } } data class Foo(val value: String) class Bar
@Configuration
# log output create: 2264edc9-1a5f-4bfc-8945-e808b12eae61 Foo(value=2264edc9-1a5f-4bfc-8945-e808b12eae61)
Beanに登録したクラスを参照先で取得します。 @Configurationの場合、BeanがCGLIBでWrapされ、method callをインターセプトしてBeanインスタンスをコンテキストから返します。 そのためinter-bean referencesが利用可能になっています。
@Component (Bean Lite Mode)
# log output create: 47224697-69bb-4b5e-8a15-a925e71eae27 create: 098e25bc-5e99-4cd6-8b0a-22a57dde0d13 Foo(value=098e25bc-5e99-4cd6-8b0a-22a57dde0d13)
Bean Lite Modeでは、Spring Containerにより通常のFactory Methodとして処理されます。つまり、CGLIB Proxyを利用しません。 そのため、inter-bean referencesは機能せず、普通にmethod callして再取得、という形になっています。ちなみにこのコードを書くとIntelliJが警告してくれます。
@Configuration(proxyBeanMethods = false)
@Componentの場合と同じになります。
proxyBeanMethods = false をつけると何が良いのか
spring-bootのissueを見たところ、パフォーマンスが良くなるみたいです。
ブログを書き終わったあとでこのissueをみつけたのですが、 ここの情報だけで何もかも解決していたので自分の書いた記事の価値とは一体、ウゴゴゴという虚無に襲われました。
まとめ
Bean Lite Modeを利用したい場合、Spring 5.2以降なら @Configuration(proxyBeanMethods = false)
を利用するのが良さそうです。
@Component
と @Configuration
についてはかなりいい加減な知識で使っていましたが、少しだけ中身を知ることができました。
記事を書いた後の感想
もうちょっとまともに英語読めるようにならないとダメダナ 😑
参考
[spring] @Configuration と @Component は違う、あるいは @Bean lite mode について - tokuhirom's blog