spring - Spring Boot @Component 不会创建 Bean
问题描述
由于根据文档@Component
为 Spring 容器注册 bean,我正在尝试使用以下代码创建一个简单的依赖注入示例:
package pl.playground;
//...
@SpringBootApplication
public class PlaygroundApplication {
@Autowired
private static Building building;
public static void main(String[] args) {
building.setBuildingSize(12L);
System.out.println(building.monthlyHeatingCost());
}
}
package pl.playground.facade;
//...
@Component
public class Building {
private HeatingService service;
private Long buildingSize;
@Autowired
public Building(HeatingService service) {
this.service = service;
}
public Double monthlyHeatingCost() {
return service.getMonthlyHeatingCost(buildingSize);
}
public void setBuildingSize(Long buildingSize) {
this.buildingSize = buildingSize;
}
}
package pl.playground.service;
public interface HeatingService {
Double getMonthlyHeatingCost(Long size);
}
package pl.playground.service;
//...
@Component
public class HeatingServiceImpl implements HeatingService {
private final Double CUBIC_PRICE = 2.3;
public HeatingServiceImpl() {}
@Override
public Double getMonthlyHeatingCost(Long size) {
return size * CUBIC_PRICE;
}
}
它构建并运行,但有一个NullPointerException
at building.setBuildingSize(12L);
。然而,下面的工作没有任何问题:
//PlaygroundApplication.java
package pl.playground;
//...
@SpringBootApplication
public class PlaygroundApplication {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
Building building = context.getBean(Building.class);
building.setBuildingSize(12L);
System.out.println(building.monthlyHeatingCost());
}
}
package pl.playground.config;
//...
@Configuration
public class Config {
@Bean
public Building building(HeatingService service) {
return new Building(service);
}
@Bean
public HeatingServiceImpl heatingServiceImpl() {
return new HeatingServiceImpl();
}
}
package pl.playground.facade;
//...
public class Building {
private HeatingService service;
private Long buildingSize;
public Building(HeatingService service) {
this.service = service;
}
public Double monthlyHeatingCost() {
return service.getMonthlyHeatingCost(buildingSize);
}
public Long getBuildingSize() {
return buildingSize;
}
public void setBuildingSize(Long buildingSize) {
this.buildingSize = buildingSize;
}
}
package pl.playground.service;
public interface HeatingService {
Double getMonthlyHeatingCost(Long size);
}
package pl.playground.service;
public class HeatingServiceImpl implements HeatingService {
private final Double CUBIC_PRICE = 2.3;
public HeatingServiceImpl() {}
@Override
public Double getMonthlyHeatingCost(Long size) {
return size * CUBIC_PRICE;
}
}
为什么
@Component
不创建 Beans?它以我认为应该在
@Controller
Web 应用程序中使用的方式工作,这有什么不同吗?究竟@Bean
和@Component
有什么不同?我不明白什么?
编辑
考虑以下场景:
package pl.playground;
//...
@SpringBootApplication
public class ExampleApplication {
public static void main(String[] args) {
SpringApplication.run(ExampleApplication.class, args);
}
}
package pl.playground.controller;
//...
@Controller
public class Controller {
private Facade facade;
@Autowired
public Controller(Facade facade) {
this.facade = facade;
}
@GetMapping("/")
public String getIndexPage(Model model) {
return "index";
}
}
package pl.playground.facade;
//...
@Component
public class Facade {
private PostsService postService;
private UserService userService;
private TagService tagService;
@Autowired
public Facade(PostsService retrieve, UserService user, TagService tag) {
this.postService = retrieve;
this.userService = user;
this.tagService = tag;
}
//...
}
我不需要@Configuration
在这里让它工作。这是我的担心。
解决方案
您的代码的问题是您正在尝试@Autowire
使用静态字段。你根本无法做到这一点。看这里:你可以将@Autowired 与静态字段一起使用吗?
它无法工作,因为PlaygroundApplication
该类不是由 spring 创建和管理的。注入仅在 spring 管理的实例中起作用。您可以将带有注释的@SpringBootApplication
类视为配置类。Spring 创建这些类的实例,并且注入在它们内部工作,但仅在实例字段上工作。
第二个示例显示了从应用程序的方法访问 spring bean 的正确方法main
。
推荐阅读
- sql - 如何在单个查询中找到数组值的出现和缺失?
- ios - 关于如何在 iOS 应用程序中创建对象的大图
- amazon-web-services - 使用 ELB TCP 在 AWS 上安装 Istio 得到 504 超时
- system-verilog - uvm configure_phase 永远不会被调用
- css - 如何使用 React-Bootstrap 平滑水平折叠过渡?
- django - Django表单如何在内部表单中显示相关数据
- cassandra - Cassandra 连接器的动态表名或查询/Flink 作业的动态接收器
- c# - 为什么 AdMob 不出现在 Xamarin 表单中
- javascript - 为什么我的代码可以在标准 Node.js 文件中运行,但不能在 AWS Lambda 函数中运行?
- reactjs - 使用 React Router V6 的单页