Spring-如何正确使用@Autowired?

时间:2019-02-16 20:56:02

标签: java spring jpa

我在Spring应用程序中发现了一个奇怪的行为。

实体的@autowired一直无法正常工作。

我使用Elide项目来构建JSONAPI和一些自定义控制器。

在一个控制器中,一个实体的@Autowrited保持为空,但是当从Elide调用时,它使用正常。

控制器:

@RestController
public class UploadController {
    @Autowired
    private ProjectRepository projectRepository;

    @PostMapping(value = "/api/projects/{projectId}/upload")
    public String uploadItem(@PathVariable long projectId, @RequestParam("file") MultipartFile file,
                              @RequestParam("projectName") String projectName,
                              RedirectAttributes redirectAttributes) throws IOException {
        Project project = projectRepository.findOneByProjectIdAndName(projectId, projectName);
        Integer result = project.getNumberOfItems();

        return "";
    }
}

实体

@Setter
@NoArgsConstructor
@Table(name = "projects")
@Entity
@Include(rootLevel = true, type = "projects")
public class Project extends DiffShelfBase {

    @Autowired
    @Transient
    private ItemRepository itemRepository;

    @Transient
    @ComputedAttribute
    public Integer getNumberOfItems() {
        return itemRepository.countByProjectId(this.getId());
    }
}

存储库

@Repository
@Transactional
public interface ItemRepository extends JpaRepository<Item, Long> {
    Integer countByProjectId(long projectId);
}

配置

@Configuration
@EnableSpringConfigured
public class MyConfiguration {
    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**")
                        .allowedMethods("*")
                        .allowedOrigins("http://localhost:4200");
            }
        };
    }
}

我不明白为什么,但是itemRepository中的Project.getNumberOfItems为空。

3 个答案:

答案 0 :(得分:3)

这不是您应该怎么做的方法。不要在您的实体中使用@Autowired。这个注释是由Spring管理的,但是您的实体是由Hibernate管理和创建的,它并不关心Spring注释。您可以找到另一种将此属性添加到实体的方法(例如,使其成为数据库中的字段)。

答案 1 :(得分:1)

您遇到的问题是,Project不能由spring管理。您必须在课程中添加@Configurable批注。然后您的Autowired批注将起作用。

但是我真的会重构您的代码。您的实体中不应包含弹簧对象。

答案 2 :(得分:0)

Entity应该是光荣的POJO,切勿使其复杂化,将其嵌入存储库中

因此在ItemRepository本身上自动上线UploadController

@RestController
public class UploadController {

    @Autowired
    private ProjectRepository projectRepo;

    @Autowired
    private ItemRepository itemRepo;

    @PostMapping(value = "/api/projects/{projectId}/upload")
    public String uploadItem(@PathVariable long projectId, @RequestParam("file") MultipartFile file,
                              @RequestParam("projectName") String projectName,
                              RedirectAttributes redirectAttributes) throws IOException {

        Project project = projectRepo.findOneByProjectIdAndName(projectId, projectName);
        Integer result = itemRepo.countByProjectId(project.getId());

        return "";
    }
}

作为一种好的实践,您总是可以进行构造函数注入,从而使其易于测试

例如代替

@Autowired
private ProjectRepository projectRepo;

@Autowired
private ItemRepository itemRepo;

进行构造函数注入

private final ProjectRepository projectRepo;
private final ItemRepository itemRepo;

@Autowired
public UploadController(final ProjectRepository projectRepo, final ItemRepository itemRepo) {
    this.projectRepo = projectRepo;
    this.itemRepo = itemRepo;
}

这样

  1. 通过传递Mockito实例很容易进行测试。
  2. 你可以做 最终(直接在变量上使用@Autowire不可能)