假设我使用Spring,我有以下策略…
接口
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调用返回空指针。
我该如何使用spring来实现上述模式并确保线程安全?我正在尝试的可能吗?
我将使用简单的依赖注入。
@Component("burger") public class BurgerStrategy implements MealStrategy { ... } @Component("sausage") public class SausageStrategy implements MealStrategy { ... }
Controller
选项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限定词而不是文本名称,以在编译时捕获拼写错误。
由于具体的策略通常是在运行时根据提供的参数左右确定的,因此我建议如下。
@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); ... }