簡體   English   中英

Spring-如何正確使用@Autowired?

[英]Spring - How to use @Autowired correctly?

我在Spring應用程序中發現了一個奇怪的行為。

實體的@autowired並非一直都在工作。

我使用的Elid項目,以建立一個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");
            }
        };
    }
}

我不明白為什么,但是Project.getNumberOfItemsitemRepository為null。

這不是您應該如何做的方法。 不要在您的實體中使用@Autowired 這個注釋是由Spring管理的,但是您的實體是由Hibernate管理和創建的,它並不關心Spring注釋。 您可以找到另一種方法將此屬性添加到您的實體(例如,使其成為數據庫中的字段)。

您遇到的問題是,您的Project沒有在春季之前進行管理。 您必須在類中添加@Configurable批注。 然后,您的自動Autowired注釋將起作用。

但是我真的會重構您的代碼。 您的實體中不應包含彈簧對象。

一個Entity應該是一個美化的POJO ,永遠不要使它復雜地嵌入repos里面。

因此,可以自動上ItemRepositoryUploadControllerUploadController本身。

@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 (直接使用@Autowire對變量進行@Autowire是不可能的)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM