A strange code error experience---when the @Validated annotation is used on the controller class, the injection fails

Problem Description

When using the @Validated annotation in the Controller class I wrote, I found that the request would report an error: Cannot invoke “com.firmSaas.business.service.DetectionIndexClassificationService.get(java.lang.Long)” because “this.classificationService” is null

package com.firmSaas.business.web;

import com.firmSaas.business.bean.dto.DetectionIndexClassificationDTO;
import com.firmSaas.business.bean.vo.DetectionIndexClassificationVO;
import com.firmSaas.business.service.DetectionIndexClassificationService;
import com.firmSaas.core.bean.WrapMapper;
import com.firmSaas.core.bean.Wrapper;
import io.swagger.annotations.ApiOperation;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;

@RestController
//当使用此注解时就会导致报错,而删除此注解时则一切正常
@Validated
@RequestMapping("/detectionIndexClassification")
public class DetectionIndexClassificationController {
    
    

    @Resource
    private DetectionIndexClassificationService classificationService;

    @PostMapping("/add")
    @ApiOperation(value = "批量新增检测指标分类")
    private Wrapper<?> add(@Valid @RequestBody List<DetectionIndexClassificationDTO> indexClassificationDTOList){
    
    
        System.out.println(classificationService);
        classificationService.add(indexClassificationDTOList);
        return WrapMapper.ok();
    }

    @PostMapping("/update")
    @ApiOperation(value = "根据ID更新检测指标分类")
    private Wrapper<?> update(@Valid @RequestBody DetectionIndexClassificationDTO indexClassificationDTO){
    
    
        classificationService.update(indexClassificationDTO);
        return WrapMapper.ok();
    }

    @DeleteMapping("/delete/{id}")
    @ApiOperation(value = "根据ID删除检测指标分类")
    private Wrapper<?> delete(@PathVariable Long id){
    
    
        classificationService.delete(id);
        return WrapMapper.ok();
    }

    @GetMapping("/get/{platformId}")
    @ApiOperation(value = "获取所有的检测指标分类")
    private Wrapper<List<DetectionIndexClassificationVO>> get(@PathVariable Long platformId){
    
    
        List<DetectionIndexClassificationVO> detectionIndexClassificationVOS = classificationService.get(platformId);
        return WrapMapper.ok(detectionIndexClassificationVOS);
    }

}


Cause Analysis:

According to the error message, when the @Validated annotation is used, the this.classificationService object will be empty. This is usually caused by the Spring framework not correctly injecting the DetectionIndexClassificationService instance.
However, the @Validated annotation usually does not cause this error because it only enables parameter validation and does not directly affect dependency injection.

Possible causes and solutions:

  • Check that the DetectionIndexClassificationService is correctly declared and configured as a Spring Bean. Make sure you use the @Service annotation on the service class or configure it correctly in the configuration file.
  • Make sure that the DetectionIndexClassificationService class is within the scope of package scanning, or bean scanning is manually configured.
  • If you create the DetectionIndexClassificationService object manually in the controller without using Spring for dependency injection, Spring will not be able to automatically inject it. In this case, you need to delete the manually created object and then inject DetectionIndexClassificationService using @Autowired or @Resource annotation.
  • If AOP (aspect-oriented programming) is used in Spring configuration, it may cause proxy issues. Please ensure that AOP is configured correctly and will not affect service injection.

After inspection, it was found that it was not caused by the above problem, and it took a long time to solve it. Just when I was having a headache, I suddenly discovered the key to the problem---access modifier.

Although the @Validated annotation is used, the private access modifier is added to the controller method. In Spring, methods modified by private will not be proxied normally, causing dependency injection to fail.


solution:

Modify the controller method access modifier to public. You must be careful when typing the code, otherwise some strange problems will occur and it will be difficult to find the problem, which is very troublesome.

package com.firmSaas.business.web;

import com.firmSaas.business.bean.dto.DetectionIndexClassificationDTO;
import com.firmSaas.business.bean.vo.DetectionIndexClassificationVO;
import com.firmSaas.business.service.DetectionIndexClassificationService;
import com.firmSaas.core.bean.WrapMapper;
import com.firmSaas.core.bean.Wrapper;
import io.swagger.annotations.ApiOperation;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;

@RestController
@Validated
@RequestMapping("/detectionIndexClassification")
public class DetectionIndexClassificationController {
    
    

    @Resource
    private DetectionIndexClassificationService classificationService;

    @PostMapping("/add")
    @ApiOperation(value = "批量新增检测指标分类")
    public Wrapper<?> add(@Valid @RequestBody List<DetectionIndexClassificationDTO> indexClassificationDTOList){
    
    
        System.out.println(classificationService);
        classificationService.add(indexClassificationDTOList);
        return WrapMapper.ok();
    }

    @PostMapping("/update")
    @ApiOperation(value = "根据ID更新检测指标分类")
    public Wrapper<?> update(@Valid @RequestBody DetectionIndexClassificationDTO indexClassificationDTO){
    
    
        classificationService.update(indexClassificationDTO);
        return WrapMapper.ok();
    }

    @DeleteMapping("/delete/{id}")
    @ApiOperation(value = "根据ID删除检测指标分类")
    public Wrapper<?> delete(@PathVariable Long id){
    
    
        classificationService.delete(id);
        return WrapMapper.ok();
    }

    @GetMapping("/get/{platformId}")
    @ApiOperation(value = "获取所有的检测指标分类")
    public Wrapper<List<DetectionIndexClassificationVO>> get(@PathVariable Long platformId){
    
    
        List<DetectionIndexClassificationVO> detectionIndexClassificationVOS = classificationService.get(platformId);
        return WrapMapper.ok(detectionIndexClassificationVOS);
    }

}

Guess you like

Origin blog.csdn.net/weixin_53902288/article/details/132853115