spring-boot 应用程序中自动装配组件时如何解决 NullPointerException
How to solve NullPointerException when Autowiring component in spring-boot application
当自动装配一个组件时,在本例中是一个@Service,我从 NullPointerException 中得到一个 BeanInstantiationException。
我正在使用基于注释的 bean 创建,据我所知,所有需要的是用 @Service、@Repository、@Component 或 @Controller 注释 class。
我已经尝试分别和组合扫描包和 classes,并且在存储库包上使用 @EnableJpaRepositories。
申请:
package com.demoApp;
import com.demoApp.backend.DAOs.UserDAO;
import com.demoApp.backend.domain.User;
import com.demoApp.backend.services.Services;
import com.demoApp.ui.views.MainView;
import com.demoApp.app.security.SecurityConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
/**
* Spring boot web application initializer.
*/
@SpringBootApplication(scanBasePackageClasses = { SecurityConfiguration.class, MainView.class, admexFront.class,
UserDAO.class, Services.class}, exclude = ErrorMvcAutoConfiguration.class,scanBasePackages = {"com.demoApp.backend.services"})
@EnableJpaRepositories(basePackages = {"com.demoApp.backend.DAOs"})
@EntityScan(basePackages = {"com.demoApp.backend.domain"})
public class admexFront extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(admexFront.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(admexFront.class);
}
}
这是服务助手 class:
package com.demoApp.backend.services;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.web.context.annotation.SessionScope;
import java.io.Serializable;
@Service(value = "Services")
@SessionScope
public class Services implements Serializable {
@Autowired
private ApplicationContext applicationContext;
public ApplicationContext getApplicationContext() {
return applicationContext;
}
public ContactService getContactService() {
return applicationContext.getBean(ContactService.class);
}
public UserService getUserService() {
return applicationContext.getBean(UserService.class);
}
}
这里是发生错误的ContactView路由:
package com.demoApp.ui.views;
import com.demoApp.app.security.SecurityUtils;
import com.demoApp.backend.domain.Client;
import com.demoApp.backend.domain.Contact;
import com.demoApp.backend.domain.User;
import com.demoApp.backend.services.Services;
import com.vaadin.flow.component.Tag;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.orderedlayout.FlexComponent;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.Route;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
@Tag("contact-view")
@Route(value = "contacts", layout = MenuBar.class)
public class ContactView extends Div {
public static String NAME = "Contacts";
public static String ROUTE = "contacts";
public static String ICON = "arrow-right";
private VerticalLayout mainLayout = new VerticalLayout();
@Autowired
private Services services;
@Autowired
public ContactView() {
User loggedInUser = SecurityUtils.getUser();
Contact userContact = loggedInUser.getContactRef();
Client client = userContact.getClientRef();
mainLayout.setDefaultHorizontalComponentAlignment(FlexComponent.Alignment.AUTO);
add(mainLayout);
List<Contact> contacts = services.getContactService().getAllContactsFromClient(client);
Grid<Contact> contactGrid = new Grid<>(Contact.class);
contactGrid.setColumns("Contact Code", "Name", "Email");
add(contactGrid);
}
}
我收到的错误信息是:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.demoApp.ui.views.ContactView': Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [co
m.demoApp.ui.views.ContactView]: Constructor threw exception; nested exception is java.lang.NullPointerException
设身处地为Spring着想。它必须构造一个 ContactView
,并填充其 services
字段。
为了能够填充对象的字段,对象需要存在,对吧?所以它必须调用构造函数来构造对象,before才能设置它的字段。因此,当构造函数被调用时,该字段不可能被填充,因此为空。因此 NullPointerException,因为您在构造函数内的字段上调用了一个方法。
解决方案:不要使用字段注入。使用构造函数注入。
// NO @Autowired here
private Services services;
@Autowired // this is actually optional unless you have another constructor
public ContactView(Services services) {
this.services = services;
// ...
当自动装配一个组件时,在本例中是一个@Service,我从 NullPointerException 中得到一个 BeanInstantiationException。
我正在使用基于注释的 bean 创建,据我所知,所有需要的是用 @Service、@Repository、@Component 或 @Controller 注释 class。 我已经尝试分别和组合扫描包和 classes,并且在存储库包上使用 @EnableJpaRepositories。
申请:
package com.demoApp;
import com.demoApp.backend.DAOs.UserDAO;
import com.demoApp.backend.domain.User;
import com.demoApp.backend.services.Services;
import com.demoApp.ui.views.MainView;
import com.demoApp.app.security.SecurityConfiguration;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
/**
* Spring boot web application initializer.
*/
@SpringBootApplication(scanBasePackageClasses = { SecurityConfiguration.class, MainView.class, admexFront.class,
UserDAO.class, Services.class}, exclude = ErrorMvcAutoConfiguration.class,scanBasePackages = {"com.demoApp.backend.services"})
@EnableJpaRepositories(basePackages = {"com.demoApp.backend.DAOs"})
@EntityScan(basePackages = {"com.demoApp.backend.domain"})
public class admexFront extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(admexFront.class, args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
return application.sources(admexFront.class);
}
}
这是服务助手 class:
package com.demoApp.backend.services;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.web.context.annotation.SessionScope;
import java.io.Serializable;
@Service(value = "Services")
@SessionScope
public class Services implements Serializable {
@Autowired
private ApplicationContext applicationContext;
public ApplicationContext getApplicationContext() {
return applicationContext;
}
public ContactService getContactService() {
return applicationContext.getBean(ContactService.class);
}
public UserService getUserService() {
return applicationContext.getBean(UserService.class);
}
}
这里是发生错误的ContactView路由:
package com.demoApp.ui.views;
import com.demoApp.app.security.SecurityUtils;
import com.demoApp.backend.domain.Client;
import com.demoApp.backend.domain.Contact;
import com.demoApp.backend.domain.User;
import com.demoApp.backend.services.Services;
import com.vaadin.flow.component.Tag;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.orderedlayout.FlexComponent;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.router.Route;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.List;
@Tag("contact-view")
@Route(value = "contacts", layout = MenuBar.class)
public class ContactView extends Div {
public static String NAME = "Contacts";
public static String ROUTE = "contacts";
public static String ICON = "arrow-right";
private VerticalLayout mainLayout = new VerticalLayout();
@Autowired
private Services services;
@Autowired
public ContactView() {
User loggedInUser = SecurityUtils.getUser();
Contact userContact = loggedInUser.getContactRef();
Client client = userContact.getClientRef();
mainLayout.setDefaultHorizontalComponentAlignment(FlexComponent.Alignment.AUTO);
add(mainLayout);
List<Contact> contacts = services.getContactService().getAllContactsFromClient(client);
Grid<Contact> contactGrid = new Grid<>(Contact.class);
contactGrid.setColumns("Contact Code", "Name", "Email");
add(contactGrid);
}
}
我收到的错误信息是:
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.demoApp.ui.views.ContactView': Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [co
m.demoApp.ui.views.ContactView]: Constructor threw exception; nested exception is java.lang.NullPointerException
设身处地为Spring着想。它必须构造一个 ContactView
,并填充其 services
字段。
为了能够填充对象的字段,对象需要存在,对吧?所以它必须调用构造函数来构造对象,before才能设置它的字段。因此,当构造函数被调用时,该字段不可能被填充,因此为空。因此 NullPointerException,因为您在构造函数内的字段上调用了一个方法。
解决方案:不要使用字段注入。使用构造函数注入。
// NO @Autowired here
private Services services;
@Autowired // this is actually optional unless you have another constructor
public ContactView(Services services) {
this.services = services;
// ...