Spring自动装配“忘了”关于依赖

时间:2019-03-16 20:05:22

标签: java 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);
    }
}

Beans类:

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();
    }
}

Scoper类:

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并将其传递给作用域构造函数。 稍后,在控制器中,rand属性为null。 Debugging into Scoper bean creation Debugging into Index controller, inspecting created Scoper bean

我在做什么错了?

1 个答案:

答案 0 :(得分:4)

您正在尝试将@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更好。