这是我的第一个Spring
申请,请原谅我对此事的无知。
我在NullPoinerException
依赖项上获得@Autowired
。
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个家属,BudgetAccountMenuFactory
和BudgetInfoPaneFactory
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();
}
}
我的无知使我相信&#34;嵌套&#34;依赖项(@Autowired
组件中的@Autowired
组件)可以正常工作。
但显然我在顶级组件上得到NullPoinerException
。
我在这里缺少什么?
什么是智能方式&#34;在依赖项中注入依赖项&#34;
答案 0 :(得分:2)
好吧,我认为我们需要澄清什么是Spring中的依赖注入。
@SpringComponent
,@Controller
,@Repository
等标记类时,spring会自动创建此类的实例。但这不是BudgetTabbedPaneFactory
,而是动态生成BudgetTabbedPaneFactory
的子类(所谓的Proxy)。 Spring context
并成为managed beans
。@Autowired
的所有方法和字段,并尝试使用前一阶段自动创建的对象的相应实例对它们进行初始化。但是当你手动创建对象时,它将存在于Spring context
之外,而Spring将不关心它及其注释。它实际上根本不了解你的课程。 Annotations只是他们自己不执行任何功能的标记。
阅读有关Spring IoC container的部分。也许它有助于为您的任务找到最佳解决方案。
P.S。对于你的情况,你应该至少把@SpringComponent
注释放在BudgetTabbedPane
上(不确定它是否适用于内部类),因为现在它不是Spring bean而不是手动创建它以让Spring注入依赖项您的。