考虑接口Action
和2个实现类:StupidAction
和SmartAction
。
[SmartAction
需要使用其他服务,但是由于在运行时创建了Action
,因此@Autowired
注释不起作用(该服务为null)。
与Spring一起使用策略模式是否错误?有解决这个问题的好方法吗?
我也可以将“ StupidAction”设置为服务,而不是实例化它。我还可以将自动装配的服务传递给方法参数中的“ doSomething”。但是这两种解决方案都非常肮脏。
一些代码示例:
public interface Action {
void doSomething();
}
public class StupidAction implements Action{
@Autowired
private MyService myService; // THIS IS NULL. because StupidAction is instanciated at runtime.
public void doSomething(){
myService.changeSomething()
}
}
//Pseudo code
@RestController
@RequestMapping(path = "/")
public class WorkflowController {
@GetMapping("")
ResponseEntity someAPI() {
Action action = new SmartAction(); //create on runtime
action.doSomething(); //NullPointerExc
}
}
您可以使用BeanFactory通过名称从上下文中动态获取Bean:
@Service
public class Service {
@Autowired BeanFactory beanFactory;
public void foo(){
DynamicBean bean = beanFactory.getBean("bean_name", DynamicBean.class)
}
}
您可以从作为ApplicationContextAware的Util服务获取Bean。
@Service
public class BeanUtility implements ApplicationContextAware {
private static ApplicationContext context;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
context = applicationContext;
}
public static <T extends Object> T getMyBean(Class<T> beanClass) {
return context.getBean(beanClass);
}
}
控制器实现如下:
@RestController
@RequestMapping(path = "/")
public class WorkflowController {
@Autowired
BeanUtility beanUtility;
@GetMapping("action")
ResponseEntity someAPI() {
MyService myService = BeanUtility.getMyBean(MyService.class); // use the util class to get a Bean of your choice
Action action = new SmartAction(myService); // Constructor based DI
return new ResponseEntity<String>(action.doSomething(), HttpStatus.CREATED);
}
}
接着是如下的SmartAction类的实现:
@Service
public class SmartAction implements Action{
private MyService myService;
public SmartAction(MyService myService){
this.myService = myService;
}
@Override
public String doSomething() {
return "Smart action : " + myService.changeSomething();
}
}