首页 > 解决方案 > 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;
    }   
}

它构建并运行,但有一个NullPointerExceptionat 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;
    }   
}

编辑

考虑以下场景:

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在这里让它工作。这是我的担心。

标签: springspring-bootjavabeans

解决方案


您的代码的问题是您正在尝试@Autowire使用静态字段。你根本无法做到这一点。看这里:你可以将@Autowired 与静态字段一起使用吗?

它无法工作,因为PlaygroundApplication该类不是由 spring 创建和管理的。注入仅在 spring 管理的实例中起作用。您可以将带有注释的@SpringBootApplication类视为配置类。Spring 创建这些类的实例,并且注入在它们内部工作,但仅在实例字段上工作。

第二个示例显示了从应用程序的方法访问 spring bean 的正确方法main


推荐阅读