5

私は 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()であり、その場合、 AccountRepositorysingletonでなければならないため、これは問題になります。

本当ですか?または、何か不足していますか?

したがって、起動時に 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 をアプリケーション コンテキストに配置します。

プロキシ パターンに基づく継承の正しい意味ですか、それとも何か不足していますか?

4

1 に答える 1

1

はい、あなたが説明したことは、基本的にSpringが@Configurationクラスを処理する方法です

すべての@Configurationクラスは、起動時に CGLIB でサブクラス化されます。サブクラスでは、子メソッドは、親メソッドを呼び出して新しいインスタンスを作成する前に、キャッシュされた (スコープされた) Bean について最初にコンテナをチェックします。

認定の質問の問題が のインスタンスを 1 つだけ持つことである場合new JdbcAccountRepository()、はい、クラスaccountRepository() @Bean内でメソッドを使用するのが最善です。@Configuration

于 2014-11-14T19:00:16.813 に答える