10

メソッドに渡されたパラメーターに基づいて、同じクラスの実装であるが異なるパラメーターで構成されている多数の Spring Bean から 1 つを選択する必要があります。

たとえば、ユーザー A がメソッドを呼び出す場合は、dooFoo()Bean A で呼び出す必要がありますが、ユーザー B の場合は、Bean B でのみ同じメソッドを呼び出す必要があります。

すべての Bean をマップに貼り付け、メソッドに渡されたパラメーターからキーを導出する以外に、これを行う「Springier」の方法はありますか?

4

4 に答える 4

14

私たちのプロジェクトではその問題に直面しており、それを Factory-Like クラスで解決しています。実行時に Bean を必要とするクライアント クラスには、Spring を介して注入されたファクトリのインスタンスがありました。

@Component
public class ImTheClient{

    @Autowired
    private ImTheFactory factory;

    public void doSomething(
            Parameters parameters) throws Exception{        
        IWantThis theInstance = factory.getInstance(parameters);        

    }

}

したがって、IWantThisインスタンスはパラメーターのランタイム値に依存しparametersます。Factory の実装は次のようになります。

@Component
public class ImTheFactoryImpl implements
        ImTheFactory {

    @Autowired
    private IWantThisBadly anInstance;
    @Autowired
    private IAlsoWantThis anotherInstance;

    @Override
    public IWantThis getInstance(Parameters parameters) {
        if (parameters.equals(Parameters.THIS)) {
            return anInstance;
        }

        if (parameters.equals(Parameters.THAT)) {
            return anotherInstance;
        }

        return null;
    }
}

したがって、ファクトリ インスタンスは、IWantThisクラスの可能な値IWantThisBadlyIAlsoWantThis両方への参照を保持しますIWantThis

于 2013-07-17T15:22:09.500 に答える
2

それらを地図に貼り付けるのは問題ないようです。Spring が管理するマップ (util:mapまたは Java 構成を使用) である場合、Spring がすべてのオブジェクト参照を所有し、それらのライフサイクルを適切に管理できるため、別の場所に作成するよりも優れています。

于 2013-07-17T15:05:17.997 に答える
2

ServiceLocatorアプリケーションコンテキストをレジストリとして使用したいようです。

クライアント コードを Spring に結合せずにキーを Bean 名にマッピングする ServiceLocator を作成するには、ServiceLocatorFactoryBeanサポート クラスを参照してください。

その他のオプションは、命名規則または注釈ベースの構成を使用することです。

たとえば、Service に で注釈を付けると仮定すると@ExampleAnnotation("someId")、次の Service Locator のようなものを使用してそれらを取得できます。

public class AnnotationServiceLocator implements ServiceLocator {

    @Autowired
    private ApplicationContext context;
    private Map<String, Service> services;

    public Service getService(String id) {
        checkServices();
        return services.get(id);
    }

    private void checkServices() {
        if (services == null) {
            services = new HashMap<String, Service>();
            Map<String, Object> beans = context.getBeansWithAnnotation(ExampleAnnotation.class);
            for (Object bean : beans.values()) {
                ExampleAnnotation ann = bean.getClass().getAnnotation(ExampleAnnotation.class);
                services.put(ann.value(), (Service) bean);
            }
        }
    }   
}
于 2013-07-18T00:25:58.063 に答える
-1

あなたが話している豆(A、B)がSessionScopeまったく問題ない場合、それらは正しく選択されます。

public class BusinessLogic {

  private BaseClassOfBeanAandB bean;

  public void methodCalledByUserAorB() {
    bean.doFoo();
  }

}
于 2013-07-17T14:10:17.890 に答える