@Autowired请求处理失败;嵌套的异常是java.lang.NullPointerException

时间:2018-12-03 12:38:37

标签: java spring

我正在尝试通过使用以下方式从现有的Spring应用程序解除依赖关系 在配置类中使用Spring @Bean,在使用它的类中使用@Autowired。

以下是主要配置类:

@Configuration
@ComponentScan(basePackages = {"com.example"})
@EnableWebMvc
public class DataLoadConfig extends WebMvcConfigurerAdapter {

    @Bean
    ActivitiesFeed activityFeed() {
        HashMap<Integer, Object> temp = new HashMap<Integer, Object>();
        return new ActivitiesFeed(temp);
    }

    ...

以下是依赖项的使用方式:

public class ActivitiesLoad {

    // ADDED
    @Autowired
    ActivitiesFeed activityFeed;

    public ActivitiesLoad(String loadType, int personCode, String outputFilter, int outputNumber) {

        ...

        // REMOVED - this approach didn't throw any errors though
        // HashMap<Integer, Object> temp = new HashMap<Integer, Object>();
        // ActivitiesFeed activityFeed = new ActivitiesFeed(temp);

        // This dependency is now @Autowired in
        feed = activityFeed.getActivities();
        ...

但是,我现在遇到以下错误:

SEVERE: Servlet.service() for servlet [dispatcher] in context with path [/DataLoads] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause
java.lang.NullPointerException
    at ac.uk.strath.t4.dataload.pure.activities.ActivitiesLoad.<init>(ActivitiesLoad.java:66)
    at ac.uk.strath.t4.dataload.controller.DataLoadController.pureActivities(DataLoadController.java:149)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    ...

请参阅原始的初始化代码,此运行没有任何问题,因此我知道依赖项有效,但想知道我是否实现了注入错误。

顺便说一句,我不拥有ActivitiesFeed源,因此我无法将任何@Components诸如注释附加到该类,因此选择将其作为@Bean放入应用程序配置类(DataLoadConfig)中。

注意:我还尝试将ActivitiesLoad构造函数代码放入run(...)方法中,只是为了解决这个问题,因为我试图从构造函数中访问依赖项,但这给了我同样的错误。理想情况下,我现在宁愿将代码保留在构造函数中,因为它是别人的代码,并且在此阶段不想冒险破坏太多:)

更新

我试图添加一个@PostConstruct方法,但是只是一个问题。然后,如示例所示,我将activityFeed属性设为私有,但还是一样。

public class ActivitiesLoad {

    @Autowired
    private ActivitiesFeed activityFeed;

    private String loadType;
    private int personCode;
    private String outputFilter;
    private int outputNumber;

    public ActivitiesLoad(String loadType, int personCode, String outputFilter, int outputNumber) {
        log.debug("Starting pure activities data load");
        this.loadType = loadType;
        this.personCode = personCode;
        this.outputFilter = outputFilter;
        this.outputNumber = outputNumber;
    }

    @PostConstruct
    public void init() {
        log.debug("Starting pure activities data load @PostConstruct");
        log.debug(activityFeed); // outputs: null
        ...

更新2

在这里,我将依赖项从构造函数中排除,而是将其放入自己的init方法中,并在创建ActivityLoad实例后调用它。但是,我仍然看到NullPointerException的问题。

ActivityLoad的实例化(现在使用创建实例后调用的init方法进行实例化):

...
ActivitiesLoad activitiesLoad = new ActivitiesLoad();
activitiesLoad.init(loadType, personCode, typeFilter, outputLimit);
...

这是包含新方法的ActivityLoad类

@Component
public class ActivitiesLoad {

    @Autowired
    private ActivitiesFeed activityFeed;

    public void init(String loadType, int personCode, String outputFilter, int outputNumber) {
        log.debug(activityFeed); // outputs: null

4 个答案:

答案 0 :(得分:2)

您需要牢记两件事。

i)如果您使用new关键字创建一个类实例,则该特定实例将不会由Spring 管理,这意味着它将不会自动装配您所请求的bean。在链中。因此,从头开始,ActivitiesFeed activityFeed总是在ActivitiesLoad实例内为null,这些实例是通过使用new ActivitiesLoad(...)

生成的

ii)第二点是关于您的更新。正如其他答案所建议的那样,您试图通过类构造函数中的注入Bean调用方法。这在任何DI框架中均不起作用,因为构造函数仅用于初始化字段引用,而不能调用它们。这就是为什么需要@PostConstruct的原因,它在bean初始化/构造函数成功完成后由Spring容器调用,因此bean引用将获得适当的实例。

因此,您有2种可能的选择:

a。,通过将ActivitiesLoad正确地自动布线为原型并传递所需的状态来维护上下文。

b。重构ActivitiesLoad以完全不保留上下文,更改构造函数以保留默认值,并在其中实现所有逻辑以及所需的params(context)方法。然后,您可以使用@Autowire

在控制器中自动装配此bean。

答案 1 :(得分:1)

ActivitiesLoad应该是Spring组件,以便能够在其中自动装配bean。 尝试使它成为其中一个弹簧组件,即@Component @Service

您仍然需要使用@PostConstruct,因为它是直接为此类情况设计的。

答案 2 :(得分:0)

之所以会这样,是因为您没有在上下文中加载组件。

您的问题缺少一些信息,但是如果您运行的是独立应用程序或Spring Boot Web应用程序,则应包含一部分逻辑,该逻辑在上下文中明确表示“请加载DataLoadConfig”。

我将引用一个链接以避免重新编写您的代码:https://www.tutorialspoint.com/spring/spring_java_based_configuration.htm

我认为您缺少第四个代码段,这实际上会导致您面临的问题。该组件不在上下文中,因此在自动装配时会得到一个空指针。

通过遵循以下示例,确保您的主机中的组件在那里。

答案 3 :(得分:0)

这已经得到回答,但是我发现本文也很好地解释了为什么自动装配的依赖项为空:

https://www.moreofless.co.uk/spring-mvc-java-autowired-component-null-repository-service/