Java `“@Autowired”依赖项上的NullPoinerException”
这是我的第一个Java `“@Autowired”依赖项上的NullPoinerException”,java,spring,spring-boot,Java,Spring,Spring Boot,这是我的第一个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.i
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();
}
}
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();
}
}
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();
}
}
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();
}
}
此类还有另外两个依赖项,BudgetCountMenuFactory
和BudgetInfoPaneFactory
BudgetAccountMenuFactory.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();
}
}
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();
}
}
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();
}
}
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
我错过了什么?
什么是“在依赖项中注入依赖项”的智能方式?好吧,我认为我们需要在春季澄清什么是依赖项注入
@SpringComponent
,@Controller
,@Repository
等,spring会自动创建该类的实例。但这将不是BudgetTabbedPaneFactory
,而是动态生成的BudgetTabbedPaneFactory
(所谓)的子类李>
Spring上下文中
,成为托管bean
@Autowired
的方法和字段,并尝试使用前一阶段自动创建的对象的适当实例初始化它们Spring上下文之外,Spring将不关心它及其注释。它其实根本不了解你的班级。只是一种标记,它们本身不执行任何功能
阅读关于的章节。也许这将有助于为您的任务找到最佳解决方案
另外,对于您的情况,您至少应该将@SpringComponent
注释置于BudgetTabbedPane
之上(不确定它是否适用于内部类),因为现在它不是Springbean,也不需要手动创建它来让Spring为您的,我认为我们需要在春季澄清什么是依赖注入
当您使用注释标记类时,@SpringComponent
,@Controller
,@Repository
等,spring会自动创建该类的实例。但这将不是BudgetTabbedPaneFactory
,而是动态生成的BudgetTabbedPaneFactory
(所谓)的子类李>
实例化之后,所有带注释的组件对于Spring都可见。它们位于Spring上下文中
,成为托管bean
然后Spring检查所有标记为@Autowired
的方法和字段,并尝试使用前一阶段自动创建的对象的适当实例初始化它们
但是,当您手动创建对象时,它将存在于Spring上下文之外,Spring将不关心它及其注释。它其实根本不了解你的班级。只是一种标记,它们本身不执行任何功能
阅读关于的章节。也许这将有助于为您的任务找到最佳解决方案
注意:对于您的情况,您至少应该将@SpringComponent
注释置于BudgetTabbedPane
之上(不确定它是否适用于内部类),因为现在它不是Spring bean,所以不要手动创建它来让Spring为您的应用程序注入依赖项。当您使用new
创建一个对象时,就像您在这里所做的new BudgetInfoPaneLayout()
那样,该对象将没有任何Spring管理的内容,比如注入的对象和属性-它们将为空。与其用new创建对象,不如将它们注入类。@csm\u dev这应该是问题的答案:)@csm\u dev我的假设是,我不需要由Spring
管理它,因为它是一个内部类,其他依赖项使用相同的builder模式,但没有“嵌套依赖项”注入时没有任何问题。当您像此处那样使用new
创建对象new BudgetInfoPaneLayout()
时,该对象将不会有任何Spring管理的内容,如注入的对象和属性-它们将为空。与其用new创建对象,不如将它们注入类。@csm\u dev这应该是问题的答案:)@csm\u dev我的假设是,我不需要由Spring
管理它,因为它是一个内部类,其他依赖项使用相同的builder模式,但没有“嵌套依赖项”注入没有任何问题。很好地注释内部类并注入它们解决了问题。。。我理解这个概念,但是代码中仍然有new
类型的组件创建linew VerticalLayout()
并且它可以工作,我不理解为什么?因为该类内部没有任何spring管理的组件。是的,@csm\u dev是正确的。换句话说,如果类中有一些Spring注释(@Autowired
,@SpringComponent
),则必须由Spring实例化。尝试将一些@Autowired
属性添加到BudgetAccountMenuLayout
或BudgetInfoPaneLayout
中,并在init()中访问它。您还将获得NullPointerException
。很好地注释内部类并注入它们解决了问题。。。我理解这个概念,但是代码中仍然有new
类型的组件创建linew VerticalLayout()
并且它可以工作,我不理解为什么?因为该类内部没有任何spring管理的组件。是的,@csm\u dev是正确的。换句话说,如果你有