Vaadin Spring 在视图中启动@autowired 字段returns null

Vaadin Spring Boot @autowired field returns null in a view

首先,由于我是 spring 引导生态系统的新手,请原谅我的问题。在我的应用程序中,我有一个 vaadin 页面,我想在其中使用存储库将用户详细信息提交给数据库。在我看来 class,我已将它们添加为 @autowired 字段,但是,在 运行 期间,我看到它们的值为 运行,因此操作失败。我知道要从@autowired 中受益,不应在构建期间新创建实例,但我无法弄清楚我应该如何自己做。这是我的 classes:

@SuppressWarnings("serial")
public class LoginAwareComposite extends Composite<Div> {

@Autowired
private ApplicationEventPublisher publisher;

public LoginAwareComposite() {
}

@Override
protected void onAttach(AttachEvent event) {
    super.onAttach(event);
    UserCredentials userPrincipal = UI.getCurrent().getSession().getAttribute(UserCredentials.class);

    if (userPrincipal != null) {
        // --- NOT LOGGED IN
        UI.getCurrent().navigate(AddressBookManagementView.class);
    } 

}

}

@SuppressWarnings("serial")
@Route(value = "account")
@Theme(value = Lumo.class, variant = Lumo.LIGHT)
public class AddressBookManagementView extends LoginAwareComposite {

private VerticalLayout pageLayout = new VerticalLayout();

public AddressBookManagementView() {
    getContent().setSizeFull();
    getContent().add(initPage());

}

private Component initPage() {
    pageLayout.getStyle().set("padding-left", "0px");
    pageLayout.getStyle().set("padding-bottom", "0px");
    pageLayout.getStyle().set("padding-right", "0px");
    pageLayout.getStyle().set("overflow", "auto");
    pageLayout.setSizeFull();

    pageLayout.add(new HeaderLayout(), new BodyLayout(), new FooterLayout());

    return pageLayout;
}

}

@SuppressWarnings("serial")
@SpringComponent
public class BodyLayout extends VerticalLayout {

// some fields

@Autowired
EmailRepository emailRepository;

@Autowired
FaxRepository faxRepository;

public BodyLayout() {
    init(); //this function inits the view, and eventually inits the on click event for submit button , which then calls my function
}

private void myFunction() {
//here i use the repository entities but they do return null although they are autowired
}

所以发生的事情是,在 BodyLayout 的构造函数中我们调用 init() 函数,该函数用于初始化布局并提供功能按钮等,init 方法中的一个子函数提供使用 myFunction 提交按钮的功能。 MyFuction 使用存储库实体,但它 returns 为空。

由于您使用的是带有 vaadin 的 springboot,因此请确保以下内容:

  • 确保像 EmailRepository 一样在存储库界面上使用 @Repository 注释。
  • 尝试为您的存储库使用构造函数注入 类 如:

像下面这样尝试:

@SuppressWarnings("serial")
@SpringComponent
@UIScope
public class BodyLayout extends VerticalLayout {

// some fields

private final EmailRepository emailRepository;

private final FaxRepository faxRepository;

@Autowired
public BodyLayout(EmailRepository emailRepository, FaxRepository faxRepository) {
    this.emailRepository = emailRepository;
    this.faxRepository = faxRepository;
    init(); //this function inits the view, and eventually inits the on click event for submit button , which then calls my function
}

private void myFunction() {
//here i use the repository entities but they do return null although they are autowired
}

我能够让它按如下方式工作:

@SuppressWarnings("serial")
@Route(value = "account")
@Theme(value = Lumo.class, variant = Lumo.LIGHT)
@UIScope
@SpringComponent
public class AddressBookManagementView extends LoginAwareComposite {

private VerticalLayout pageLayout = new VerticalLayout();

@Autowired
BodyLayout bodyLayout;

public AddressBookManagementView(BodyLayout bodyLayout) {
    this.bodyLayout = bodyLayout;
    getContent().setSizeFull();
    getContent().add(initPage());

}

private Component initPage() {
    pageLayout.getStyle().set("padding-left", "0px");
    pageLayout.getStyle().set("padding-bottom", "0px");
    pageLayout.getStyle().set("padding-right", "0px");
    pageLayout.getStyle().set("overflow", "auto");
    pageLayout.setSizeFull();

    pageLayout.add(new HeaderLayout(), bodyLayout, new FooterLayout());

    return pageLayout;
}

那么BodyLayout就是

@SuppressWarnings("serial")
@UIScope
@SpringComponent
public class BodyLayout extends VerticalLayout {

private final EmailRepository emailRepository;

private final FaxRepository faxRepository;

@Autowired
public BodyLayout(EmailRepository emailRepository, FaxRepository faxRepository) {
    this.emailRepository = emailRepository;
    this.faxRepository = faxRepository;
    init();
}

大约只有 @Route、布局和 vaadin init 侦听器参与自动依赖注入(即:vaadin spring 集成要求 spring 上下文来构建它们) .如果你这样做 new MyClass() 永远不会 参与 DI。使用基于字段的注入 @Autowired 隐藏了这个问题 - 所以使用基于构造函数的注入是“行业标准”。另一种方法是不构建自己的实例,如果你想参与 DI 但要求 spring 上下文为你构建一个实例。