【问题标题】:How to inject service in controller's method?如何在控制器的方法中注入服务?
【发布时间】:2020-07-01 12:41:56
【问题描述】:

我在控制器方法中注入服务时遇到问题。我有以下服务:

@Service
@RequiredArgsConstructor
public class CreateFranchiseUseCase {
    private final FranchiseService franchiseService;
    private final UserService userService;
    private final ACLEntryService aclEntryService;
    private final FranchiseDTOMapper franchiseDTOMapper;

    public Franchise execute(CreateFranchiseDTO dto) {
        // ...
    }
}

然后在Controller中:

@RestController
@RequiredArgsConstructor
public class FranchiseController {

    // ...
    
    @PostMapping("/api/franchises")
    public ResponseEntity<Object> createFranchise(CreateFranchiseDTO dto, CreateFranchiseUseCase useCase) {
        Frachise franchise = useCase.execute(dto);
        // ...
    }
}

当我调用这个端点时,我得到 NullPointerException。异常发生在执行方法和调试方法我发现所有属性:franchiseServiceuserServiceaclEntryServicefranchiseDTOMapper都是NULL。

所有类:FranchiseServiceUserServiceACLEntryService 都带有 @Service 注释。并且FranchiseDTOMapper 被注释为@Mapper(componentModel = "spring")

Spring 是否支持方法注入?或者有什么方法可以在createFranchise() 方法中请求CreateFranchiseUseCase 类的实例,如下所示:

@PostMapping("/api/franchises")
public ResponseEntity<Object> createFranchise(CreateFranchiseDTO dto) {
    CreateFranchiseUseCase useCase = container.get(CreateFranchiseUseCase.class) // <-- something like this
    Frachise franchise = useCase.execute(dto);
    // ...
}

【问题讨论】:

  • 好吧,你不知道。您应该通过构造函数将其注入实例级属性,而不是作为方法参数。
  • 也许应该可以从 ApplicationContext 获取 bean。

标签: java spring spring-boot dependency-injection autowired


【解决方案1】:

Spring 是否支持方法注入?

没有。此处列出了按参数接收的对象:

你可以使用ApplicatonContext#getBean():

    @Autowired
    private ApplicationContext context;

    @PostMapping("/api/franchises")
    public ResponseEntity<Object> createFranchise(CreateFranchiseDTO dto) {
        reateFranchiseUseCase useCase = context.getBean(CreateFranchiseUseCase.class);
        // ...
    }

如果每个请求都需要CreateFranchiseUseCase对象实例化,则需要添加@Scope(WebApplicationContext.SCOPE_REQUEST)

@Service
@Scope(WebApplicationContext.SCOPE_REQUEST)
public class CreateFranchiseUseCase {

【讨论】:

    【解决方案2】:

    据我所知,不可能让 Spring 将对象注入方法中。
    相反,您可以让 Spring 通过控制器的构造函数注入对象。

    这会导致这样的事情:

    @RestController
    public class FranchiseController {
    
        private final CreateFranchiseUseCase createFranchiseUseCase;
    
        public FranchiseController(CreateFranchiseUseCase createFranchiseUseCase) {
            this.createFranchiseUseCase = createFranchiseUseCase;
        }
    
        @PostMapping("/api/franchises")
        public ResponseEntity<Object> createFranchise(CreateFranchiseDTO dto) {
            Frachise franchise = createFranchiseUseCase.execute(dto);
            // ...
        }
    }
    

    即使您使用 Lombok 创建构造函数,这也应该可以工作。

    【讨论】:

      【解决方案3】:

      你可以像这样注入它,但考虑通过你的控制器构造函数注入服务。

      @PostMapping("/api/franchises")
      public ResponseEntity<Object> createFranchise(CreateFranchiseDTO dto) {
          CreateFranchiseUseCase useCase = new CreateFranchiseUseCase();
          Frachise franchise = useCase.execute(dto);
          // ...
      }
      

      编辑: 但请记住,您必须向 CreateFranchiseUseCase 注入其他服务。您可以像这样在构造函数中执行此操作:

      public CreateFranchiseUseCase () {
          FranchiseService franchiseService = new FranchiseService();
          UserService userService = new UserService();
          ACLEntryService aclEntryService = new ACLEntryService();
          FranchiseDTOMapper franchiseDTOMapper = new FranchiseDTOMapper();
      }
      

      或者只是在没有构造函数的情况下注入它:

      @Service
      @RequiredArgsConstructor
      public class CreateFranchiseUseCase {
          private final FranchiseService franchiseService = new FranchiseService();
          private final UserService userService = new UserService();
          private final ACLEntryService aclEntryService = new ACLEntryService();
          private final FranchiseDTOMapper franchiseDTOMapper = new FranchiseDTOMapper();
      
          public Franchise execute(CreateFranchiseDTO dto) {
              // ...
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2017-12-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多