私は Spring Core 認定のために勉強していますが、プロキシの概念に関連するいくつかの疑問を見つけています。
そのため、教材で次のクイズを見つけました。
次のメソッドを含むJava構成クラスがあります。
@Bean
public AccountRepository accountRepository(){
return new JdbcAccountRepository();
}
@Bean
public TransferService transferService1() {
TransferServiceImpl service = new TransferServiceImpl();
service.setAccountRepository(accountRepository());
return service;
}
@Bean
public TransferService transferService2() {
return new TransferServiceImpl( new JdbcAccountRepository() );
}
ご覧のとおり、 TransferServiceImplオブジェクトを作成して返す、それぞれtransferService1()およびtransferService2()という名前のtransferService()の 2 つの異なる実装があります。
最初のものは、新しいTransferServiceImplオブジェクトを作成し、それに対してsetAccountRepository()メソッドを呼び出します。
2 つ目は単純に、新しいJdbcAccountRepositoryオブジェクトをコンストラクターに渡すTransferServiceImplを作成します。
それは私に尋ねます **前の2つの方法の中で最も良い実装はどれですか?
提供される答えは次のとおりです。専用メソッドへの呼び出しを優先します。ですから、最初の実装が最善の方法であると言っていると思います。
AccountRepository Bean はシングルトン(Spring の Bean の標準スコープであるため) であるが、JdbcAccountRepository()は 2 回以上呼び出される可能性があることを説明しています (たとえば、前のコード スニペットでは、メソッドが呼び出されたときに呼び出されます)。 transferService1()およびtransferService2()であり、その場合、 AccountRepositoryはsingletonでなければならないため、これは問題になります。
本当ですか?または、何か不足していますか?
したがって、起動時に foreach 構成クラス ( @Configurationで注釈が付けられている) が構成クラスを拡張する子クラスを作成することを収集します。
たとえば、次の構成クラスがあるとします。
@Configuration
public class AppConfig {
@Bean public AccountRepository accountRepository() { ... }
@Bean public TransferService transferService() { ... }
}
私のAppConfigを拡張する次のクラスが自動的に作成されます。
public class AppConfig$$EnhancerByCGLIB$ extends AppConfig {
public AccountRepository accountRepository() { // ... }
public TransferService transferService() { // ... }
...
...
...
}
したがって、子クラスはエントリ ポイント (呼び出されるメソッドは、子クラスで定義されたものです) であり、疑似コードは次のようになります。
public class AppConfig$$EnhancerByCGLIB$ extends AppConfig {
public AccountRepository accountRepository() {
// if bean is in the applicationContext return bean
// else call super.accountRepository() and store bean in context
}
public TransferService transferService() {
// if bean is in the applicationContext, return bean
// else call super.transferService() and store bean in context
}
}
したがって、Spring がシングルトンの問題をどのように処理できるかは明らかです。構成クラスを拡張するプロキシ クラスでメソッドを呼び出し、要求された Bean が applicationContext に存在する場合はこの Bean を返し、そうでない場合は作成するスーパー クラスで同じメソッドを呼び出します。新しい Bean をアプリケーション コンテキストに配置します。
プロキシ パターンに基づく継承の正しい意味ですか、それとも何か不足していますか?