3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

【Spring】Java Configurationでよく見る 'あの' 気持ち悪いコードを読み解く。

Posted at

よく見る気持ち悪い(気持ち悪かった)サンプルコード

Qiitaや参考書なんかでSpringのアノテーションベースConfigurationのサンプルコードを見るとたまに出くわすこんなコード。

@Configuration
public class Config {
	
	@Bean
	public Bean1 bean1() {
		return new Bean1();
	}
	
	@Bean
	public Bean2 bean2() {
		return new Bean2(bean1());//Bean1を2回newしてない???
	}

}

Bean2はBean1を引数にとってインスタンス化するのですが、Bean1を取得する手段がメソッド呼び出し。。。
初めて見たとき、「あれ?これコンテナに詰めたBean1とBean2のコンストラクタに渡したBean1が同一じゃ無いけどいいの???」って思ってそれから最近までずっとモヤモヤしてたんですが。。。

ごん、お前だったのか

メソッドbean2の中でコンテナからBean1を引っ張って標準出力してみる遊びをしたところ、


	@Bean
	public Bean1 bean1() {
		return new Bean1();
	}
	
	@Bean
	public Bean2 bean2(Bean1 bean1) {
		System.out.println(bean1);//コンテナからとってきたBean1
		System.out.println(bean1());//メソッドbean1のなかで再びnewしていると思われるBean1
		return new Bean2(bean1());
	}

結果
com.example.demo.Bean1@332b70df
com.example.demo.Bean1@332b70df

同じインスタンスじゃないか。確かに、メソッドbean2で呼び出したメソッドbean1内でnewしているはずなのに。
まさに野良狐だと思って撃ったら「ごん」だった兵十の気持ちです。

何が起こっていたのか

じゃあメソッドbean1の中で何が起こっているのか。
試しにConfigのコンストラクタでthisを標準出力してみましょう。

	public Config() {
		System.out.println(this);
	}
出力
com.example.demo.Config$$EnhancerBySpringCGLIB$$74a9b1d8@6ac168f5

EnhancerBySpringCGLIBとは何でしょう、調べてみるとProxyのことらしいですね。
実は実行時に動くConfigインスタンスはSpringが勝手に(?)作ったProxyクラスのインスタンスでメソッドbean1はその独自クラスの中でOverrideされてるっぽいです。
つまり、オリジナルのメソッドbean1は1度しか呼ばれず、2回目以降は上書きされたメソッドがコンテナからBean1を返却していたということです。

サンプルコードは間違ってなかった

気持ち悪いとか言ってしまい大変申し訳ありませんでした。

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?