web-dev-qa-db-ja.com

春の豆の戦略パターン

私が春を使用しているとしましょう、私は以下の戦略を持っています...

インターフェース

public interface MealStrategy {
    cook(Meat meat);
}

最初の戦略

@Component
public class BurgerStrategy  implements
MealStrategy {
  @Autowired CookerDao cookeryDao;

  @Override
  public void cook(Meat meat) {
      cookeryDao.getBurger(meat);
  }
}

次の戦略...

@Component
public class SausageStrategy  implements
MealStrategy {
  @Autowired CookerDao cookeryDao;

  @Override
  public cook(Meat meat) {
      return cookeryDao.getSausage(meat);
  }
}

環境...

@Component
@Scope("prototype")
public class MealContext {
    private MealStrategy mealStrategy;

    public void setMealStrategy(MealStrategy strategy) {
        this.strategy = strategy;
    }

    public void cookMeal(Meat meat) {
        mealStrategy.cook;
    }
}

次に、このコンテキストがmvcコントローラーを介してアクセスされていたとします。

@Autowired
private MealContext mealContext;

@RequestMapping(method = RequestMethod.POST)
public @ResponseBody Something makeMeal(Meat meat) {
    mealContext.setMealStrategy(new BurgerStrategy())
    mealContext.cookMeal(meat);
}

コンテキストはコンポーネントである必要がありますか?そうすると、loadOnStartupと言うエラーが表示されます。予想通り、この戦略にはnonUniqueBeanがあります。すべてのBeanは上記のようなコンポーネントである必要がありますか、それとも注釈が正しくありませんか?

私の最大のクエリは本当に、Spring MVCアプリでそのようなコンテキストを使用できるかどうかです。 @Scope(prototype)を使用する際の問題も、Daoが挿入されないため、戦略のcookeryDao呼び出しがnullポインターを返すことを意味します。

スプリングを使用して上記のパターンをどのように実装し、スレッドセーフにすることができますか?私がやろうとしていることは可能ですか?

24
david99world

単純な依存性注入を使用します。

@Component("burger")
public class BurgerStrategy implements MealStrategy { ... }

@Component("sausage")
public class SausageStrategy implements MealStrategy { ... }

コントローラ

オプションA:

@Resource(name = "burger")
MealStrategy burger;

@Resource(name = "sausage")
MealStrategy sausage;

@RequestMapping(method = RequestMethod.POST)
public @ResponseBody Something makeMeal(Meat meat) {
    burger.cookMeal(meat);
}

オプションB:

@Autowired
BeanFactory bf;

@RequestMapping(method = RequestMethod.POST)
public @ResponseBody Something makeMeal(Meat meat) {
    bf.getBean("burger", MealStrategy.class).cookMeal(meat);
}

コンパイル時にスペルミスを検出するために、テキスト名の代わりにJSR-330修飾子を作成することを選択できます。

以下も参照してください。

スプリングで戦略パターンを効率的に実装する方法?

@ Resource vs @Autowired

31
anttix

具体的な戦略は、提供されたパラメータなどに基づいて実行時に決定されることが非常に多いため、次のように提案します。

@Component
public class BurgerStrategy implements MealStrategy { ... }

@Component
public class SausageStrategy implements MealStrategy { ... }

次に、そのような戦略をすべて、指定されたコントローラーのマップ(Bean名をキーとして)に挿入し、要求に応じてそれぞれの戦略を選択します。

@Autowired
Map<String, MealStrategy> mealStrategies = new HashMap<>;

@RequestMapping(method=RequestMethod.POST)
public @ResponseBody Something makeMeal(@RequestParam(value="mealStrategyId") String mealStrategyId, Meat meat) {
    mealStrategies.get(mealStrategyId).cook(meat);

    ...
}
64
pgiecek