【问题标题】:How to solve NullPointerException when Autowiring component in spring-boot application在spring-boot应用程序中自动装配组件时如何解决NullPointerException
【发布时间】:2019-10-27 03:18:10
【问题描述】:

当自动装配组件时,在本例中为 @Service,我从 NullPointerException 中获得 BeanInstantiationException。

我正在使用基于注释的 bean 创建,据我所知,所有需要的是使用 @Service、@Repository、@Component 或 @Controller 注释类。 我尝试单独扫描包和类并组合在一起,并在存储库包上使用@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);
    }
}

这里是服务助手类:

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

【问题讨论】:

  • 由于您的ContactView 中引发了异常,您可能应该将其包括在内。没有看到这一点,我的猜测是您使用字段注入但尝试访问构造函数中的自动装配字段。请尝试改用constructor injection,然后告诉我结果如何。
  • 我同意@kaspar,因为错误来自 ContactView,如果没有看到此文件就无法识别。构造函数的问题
  • 谢谢,也添加了ContactView
  • 这个设计有很多问题。我建议您了解模型视图控制器模式。还要了解什么是依赖注入以及如何使用 Spring。
  • 再次感谢@Kaspar - 它确实解决了问题

标签: java hibernate spring-boot autowired vaadin-flow


【解决方案1】:

设身处地为春天着想。它必须构造一个ContactView,并填充它的services 字段。

为了能够填充对象的字段,对象需要存在,对吗?所以它必须调用构造函数来构造对象,能够设置它的字段之前。因此,当调用构造函数时,该字段可能还不能被填充,因此为空。因此出现 NullPointerException,因为您在构造函数内的字段上调用了一个方法。

解决方案:不要使用字段注入。使用构造函数注入。

// NO @Autowired here
private Services services;

@Autowired // this is actually optional unless you have another constructor
public ContactView(Services services) {
    this.services = services;
    // ...

【讨论】:

  • 非常感谢您的解释 - 这解决了它!
猜你喜欢
  • 2018-07-28
  • 1970-01-01
  • 2015-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-06
  • 2017-05-22
  • 1970-01-01
相关资源
最近更新 更多