首页 > 解决方案 > Spring自动装配“忘记”了依赖

问题描述

我想玩弄不同类型的 bean 范围。所以我写了一个测试环境,它应该生成一个随机数,这样我就可以看到一个 bean 是否发生了变化。我的测试设置不起作用,我无法解释我发现了什么。

我将 Spring Boot 2.13 与 Spring Framework 5.15 一起使用。

以下设置:

主类:

package domain.webcreator;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class WebcreatorApplication {

    public static void main(String[] args) {
        SpringApplication.run(WebcreatorApplication.class, args);
    }
}

豆类:

package domain.webcreator;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.Random;

@Configuration
public class Beans {
    @Bean
    public Random randomGenerator() {
        return new Random();
    }
}

范围类:

package domain.webcreator;

import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

import java.util.Random;

@Service
@Scope("singleton")
public class Scoper {
    private Random rand;

    public Scoper(Random rand) {
        this.rand = rand;
    }

    public int getNumber(int max) {
        return rand.nextInt(max);
    }
}

索引控制器

package domain.webcreator.controller;

import domain.webcreator.Scoper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class IndexController {
    @GetMapping("/")
    @ResponseBody
    @Autowired
    public String indexAction(Scoper scoper) {
        return String.valueOf(scoper.getNumber(50));
    }
}

我的问题是,我在调用scoper.getNumber(50)时得到了 NPE 。这很奇怪,因为在调试时,会生成一个 Random bean 并将其传递给 scoper 构造函数。稍后,在控制器中,rand 属性为空。 调试范围 bean 创建 调试 Index 控制器,检查创建的 Scoper bean

我究竟做错了什么?

标签: javaspring

解决方案


您正在尝试应用@Autowired随机方法,这不是 Spring 的工作方式。控制器方法参数用于特定于该 HTTP 请求的信息,而不是一般依赖项,因此 Spring 正在尝试创建一个Scoper与请求关联的新参数——但它在请求中没有任何传入值要填写。(我真的很惊讶你没有收到关于没有默认构造函数的错误。)

相反,将你Scoper的传入构造函数。

@RestController
public class IndexController {
    private final Scoper scoper;

    public IndexController(Scoper scoper) {
        this.scoper = scoper;
    }

    @GetMapping("/")
    public String indexAction(Scoper scoper) {
        return String.valueOf(scoper.getNumber(50));
    }
}

几点注意事项:

  • 单例范围是默认的,无需指定。
  • @RestController@ResponseBody除非你有一个混合控制器类,否则最好重复。

推荐阅读