考虑一个接口 Action
,以及2个实现类。StupidAction
和 SmartAction
.
SmartAction
需要使用另一个服务,但由于一个 Action
是在运行时创建的。@Autowired
注解不工作(服务为空)。
使用策略模式与 春天? 这个问题有什么好的解决办法吗?
我可以把 "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
}
}
你可以通过名称动态地从上下文中获取Bean,使用 BeanFactory:
@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();
}
}