是否有一种通用的方式将自动连接的服务传递给自实例化的视图?假设我们有一个由Spring (@Autowired works)管理的VerticalLayout和一个HorizontalLayout按钮。我们需要创建多个HorizontalLayout实例,并且按钮执行服务的一些动作(@Autowired不起作用,service为null)。解决这个问题的最佳实践是什么?将服务作为参数传递给HorizontalLayout的构造函数是一种选择,但也许还有更好的方法。
@Service
public class SomeService {
public void someMethod(){
// do something
}
}
@SpringView(name = "SomeView")
@ViewScope
public class SomeView extends VerticalLayout {
@Autowired
private SomeService service;
public SomeView(){
addComponent(new Subview());
addComponent(new Subview());
}
}
public class SubView extends HorizontalLayout {
@Autowired
private SomeService service;
public SubView(){
Button btn = new Button("Test");
btn.addClickListener(e->service.someMethod());
addComponent(btn);
}
}
编辑:我添加了一个代码示例。SubView的对象为service获取null。解决方案是将服务传递给构造函数。但我想知道,是否有更好的解决方案。
你指的是vadin View还是普通的Component?View必须实现View接口(com.vaadin.navigator.View),因此你可以使用构造函数自动连接Service和enter()方法来创建ui:
@SpringView(name = "SomeView")
@ViewScope
public class SomeView extends VerticalLayout implements View {
private SomeService service;
@Autowired
public SomeView(SomeService service){
this.service = service;
}
@Override
public void enter(ViewChangeListener.ViewChangeEvent event) {
//service is available here
removeAllComponents();
addComponent(new Subview());
addComponent(new Subview());
}
}
它的工作方式是,Spring将实例化SomeView,并在此过程中通过构造函数自动调用你的服务。然后,当视图被调用时,它将使用enter()方法来绘制其组件。
如果它只是一个常规组件(我认为这是你的情况),那么在方法中使用@PostConstruct注释而不是enter()。例如:
@Autowired
public SomeView(SomeService service){
this.service = service;
}
@PostConstruct
public void init() {
//service is available here
addComponent(...);
}
我没有测试过这个注释,但它在Vaadin中有广泛的文档记录。请让我知道它是否适合你。