gpt4 book ai didi

java - `NullPoinerException` 依赖于 `@Autowired`

转载 作者:行者123 更新时间:2023-12-02 02:46:03 29 4
gpt4 key购买 nike

这是我的第一个 Spring 应用程序,所以请原谅我对此事的无知。

我在 @Autowired 依赖项上遇到 NullPoinerException

14:08:48,415 SEVERE [com.vaadin.server.DefaultErrorHandler] (default task-4) : java.lang.NullPointerException
at com.letifer.ui.factory.BudgetTabbedPaneFactory$BudgetTabbedPane.init(BudgetTabbedPaneFactory.java:26)
at com.letifer.ui.factory.BudgetTabbedPaneFactory.createComponent(BudgetTabbedPaneFactory.java:44)
at com.letifer.ui.commons.BudgetMainUI.init(BudgetMainUI.java:44)

BudgetTabbedPaneFactory.java:

package com.letifer.ui.factory;

import org.springframework.beans.factory.annotation.Autowired;

import com.letifer.utils.constants.BudgetStringConstants;
import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.ui.Component;
import com.vaadin.ui.Label;
import com.vaadin.ui.TabSheet;
import com.vaadin.ui.VerticalLayout;

@SpringComponent
public class BudgetTabbedPaneFactory implements BudgetComponent {

private class BudgetTabbedPane extends VerticalLayout {

private TabSheet tabSheet;

@Autowired
BudgetAccountsFactory accountsFactory;

Component accounts;

public BudgetTabbedPane init() {
tabSheet = new TabSheet();
accounts = accountsFactory.createComponent(); // <-- NullPoinerException
return this;
}

public BudgetTabbedPane layout() {
setSizeFull();
tabSheet.addTab(accounts, BudgetStringConstants.ACCOUNTS_TAB_NAME.getName());
tabSheet.addTab(new Label(BudgetStringConstants.BALANCE_TAB_NAME.getName()), BudgetStringConstants.BALANCE_TAB_NAME.getName());
tabSheet.addTab(new Label(BudgetStringConstants.STATISTICS_TAB_NAME.getName()), BudgetStringConstants.STATISTICS_TAB_NAME.getName());

addComponent(tabSheet);

return this;
}

}

public Component createComponent() {
return new BudgetTabbedPane().init().layout();
}

}

此类具有 BudgetAccountsFactory 依赖项

BudgetAccountsFactory.java:

package com.letifer.ui.factory;

import org.springframework.beans.factory.annotation.Autowired;

import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Component;
import com.vaadin.ui.HorizontalLayout;

@SpringComponent
public class BudgetAccountsFactory implements BudgetComponent {

@Autowired
private BudgetAccountMenuFactory accountMenuFactory;

@Autowired
private BudgetInfoPaneFactory infoPaneFactory;

private class BudgetAccountsLayout extends HorizontalLayout {

Component menu;
Component infoPane;

public BudgetAccountsLayout init() {

menu = accountMenuFactory.createComponent();
infoPane = infoPaneFactory.createComponent();

return this;
}

public BudgetAccountsLayout layout() {

setMargin(true);
setSizeFull();

addComponent(menu);
setComponentAlignment(menu, Alignment.TOP_LEFT);
setExpandRatio(menu, 1);

addComponent(infoPane);
setComponentAlignment(infoPane, Alignment.TOP_LEFT);
setExpandRatio(infoPane, 2);

return this;
}

}

public Component createComponent() {
return new BudgetAccountsLayout().init().layout();
}

}

此类还有另外 2 个依赖项,BudgetAccountMenuFactoryBudgetInfoPaneFactory

BudgetAccountMenuFactory.java:

package com.letifer.ui.factory;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import com.letifer.utils.constants.BudgetStringConstants;
import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.ui.Component;
import com.vaadin.ui.ListSelect;
import com.vaadin.ui.VerticalLayout;

@SpringComponent
public class BudgetAccountMenuFactory implements BudgetComponent {

private class BudgetAccountMenuLayout extends VerticalLayout {

private ListSelect<String> options;

public BudgetAccountMenuLayout init() {
options = new ListSelect<String>(BudgetStringConstants.ACCOUNTS_MENU_OPTION_TITLE.getName());
List<String> optionsList = new ArrayList<String>(Arrays.asList(BudgetStringConstants.ACCOUNTS_MENU_OPTION_SHOW_ACCOUNTS.getName(),
BudgetStringConstants.ACCOUNTS_MENU_OPTION_ADD.getName(), BudgetStringConstants.ACCOUNTS_MENU_OPTION_REMOVE.getName()));
Set<String> optionsSet = new HashSet<String>(optionsList);
options.setValue(optionsSet);
return this;
}

public BudgetAccountMenuLayout layout() {
setMargin(true);
setSizeFull();

addComponent(options);
return this;
}

}

public Component createComponent() {
return new BudgetAccountMenuLayout().init().layout();
}

}

BudgetInfoPaneFactory.java:

package com.letifer.ui.factory;

import com.vaadin.spring.annotation.SpringComponent;
import com.vaadin.ui.Component;
import com.vaadin.ui.Label;
import com.vaadin.ui.VerticalLayout;

@SpringComponent
public class BudgetInfoPaneFactory implements BudgetComponent {

private class BudgetInfoPaneLayout extends VerticalLayout {

public static final String VIEW_NAME = "info";

private Label label;

public BudgetInfoPaneLayout init() {
label = new Label("INFO HERE");
return this;
}

public BudgetInfoPaneLayout layout() {
setMargin(true);
setSizeFull();
addComponent(label);
return this;
}

}

public Component createComponent() {
return new BudgetInfoPaneLayout().init().layout();
}

}

我的无知让我相信“嵌套”依赖项(@Autowired 组件内的 @Autowired 组件)会很好地工作。

但显然我在顶部组件上遇到了 NullPoinerException

我在这里缺少什么?

“在依赖项中注入(inject)依赖项”的智能方式是什么?

最佳答案

嗯,我认为我们需要澄清什么是 Spring 中的依赖注入(inject)。

  1. 当您使用注释@SpringComponent@Controller@Repository等标记类时,Spring会自动创建此类的实例。但这不是 BudgetTabbedPaneFactory ,而是动态生成的 BudgetTabbedPaneFactory 子类(所谓的 Proxy )。
  2. 实例化后,所有带注释的组件对于 Spring 都是可见的。它们位于 Spring 上下文 中并成为托管 bean
  3. 然后 Spring 检查所有标有 @Autowired 的方法和字段,并尝试使用上一阶段自动创建的对象的适当实例来初始化它们。

但是当您手动创建对象时,它将存在于Spring上下文之外,并且Spring不会关心它及其注释。它实际上根本不知道你的类(class)。 Annotations只是一种标记,它们本身不执行任何功能。

阅读有关 Spring IoC container 的部分。也许这将有助于找到适合您任务的最佳解决方案。

附注对于您的情况,您至少应该将 @SpringComponent 注释放在 BudgetTabbedPane 上(不确定它是否适用于内部类),因为现在它不是 Spring bean 并且不要创建它手动让 Spring 为您注入(inject)依赖项。

关于java - `NullPoinerException` 依赖于 `@Autowired`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44566408/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com