首页 > 解决方案 > UnsatisfiedDependencyException 和循环依赖

问题描述

我正在尝试构建和运行一些 Spring Boot 遗留代码,但它失败了:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'dataLoader' defined in file [......\bootstrap\DataLoader.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'organizationServiceImpl': Unsatisfied dependency expressed through method 'setAssessmentService' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'assessmentServiceImpl': Invocation of init method failed; nested exception is org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet
    
......
    
    at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
Caused by: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'organizationServiceImpl': Unsatisfied dependency expressed through method 'setAssessmentService' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'assessmentServiceImpl': Invocation of init method failed; nested exception is org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredMethodElement.inject(AutowiredAnnotationBeanPostProcessor.java:676)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:90)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:374)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1411)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:592)
    at ........
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'assessmentServiceImpl': Invocation of init method failed; nested exception is org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet
    at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:139)

DataLoader 类是:

@Component
public class DataLoader implements ApplicationRunner {

    private final OrganizationService organizationService;

    private List<String> organizationNames = Arrays.asList(
        ...some long list of string literals...

    );

    public DataLoader(OrganizationService organizationService) {
        this.organizationService = organizationService;
    }

    @Override
    public void run(ApplicationArguments args) {
        if (CollectionUtils.isEmpty(organizationService.findAll())) {
            addOrganizations();
        }
    }

    private void addOrganizations() {
        organizationNames.forEach(name -> {
            OrganizationRequest organization = new OrganizationRequest();
            organization.setName(name);
            if (
            ....irrelevant code....
            }
            organizationService.save(organization);
        });
    }

}

和 OrganizationServiceImpl 类是:

@Service
public class OrganizationServiceImpl implements OrganizationService {

    private final OrganizationRepository organizationRepository;
    private final AddressService addressService;
    private final ContactService contactService;
    private final SupplierQualifierService supplierQualifierService;
    private final MonitoringScopeService monitoringScopeService;
    private final FinancialService financialsService;

    private DocumentService documentService;
    private AssessmentService assessmentService;

    @Getter
    private Map<Long, Set<QuestionType>> questionTypesForAssessmentByOrganization = new HashMap<>();

    public OrganizationServiceImpl(OrganizationRepository organizationRepository, AddressService addressService, ContactService contactService, SupplierQualifierService supplierQualifierService, MonitoringScopeService monitoringScopeService, FinancialService financialsService ) {
        this.organizationRepository = organizationRepository;
        this.addressService = addressService;
        this.contactService = contactService;
        this.supplierQualifierService = supplierQualifierService;
        this.monitoringScopeService = monitoringScopeService;
        this.financialsService = financialsService;
    }

    //workaround for circular dependency
    @Autowired
    public void setAssessmentService(AssessmentService assessmentService) {
        this.assessmentService = assessmentService;
    }

    // to prevent circular dependency problem ...
    @Autowired 
    public void setDocumentService(DocumentService documentService) {
        this.documentService = documentService;
    }

    @Override
    public Organization findById(Long id) {
        Optional<Organization> organization = organizationRepository.findById(id);
        return organization.orElse(new Organization());
    }

    @Override
    public List<Organization> findAll() {
        return organizationRepository.findAll();
    }

    @Override
    public Organization save(OrganizationRequest request) {
    ....long not relevant code...

        return savedOrganization;
    }


    ....long not relevant code, some business logic...

}

AssessmentServiceImpl 类是:

@Service
public class AssessmentServiceImpl implements AssessmentService {

private final AssessmentRepository assessmentRepository;
private final OrganizationService organizationService;
private final AnswerService answerService;
private final QuestionService questionService;

private Map<QuestionType, Integer> numberOfQuestionsByType = new HashMap<>();

public AssessmentServiceImpl(AssessmentRepository assessmentRepository, OrganizationService organizationService, AnswerService answerService, QuestionService questionService) {
    this.assessmentRepository = assessmentRepository;
    this.organizationService = organizationService;
    this.answerService = answerService;
    this.questionService = questionService;
}

@PostConstruct
public void postConstruct() {
    for (QuestionType type : QuestionType.values()) {
        numberOfQuestionsByType.put(type, questionService.findByQuestionType(type).size());
    }
}


... some business logic code....

}

失败的依赖注入链是:

Error creating bean with name 'dataLoader':
Error creating bean with name 'organizationServiceImpl': 
Error creating bean with name 'assessmentServiceImpl': 

但我看不出有直接原因。

我看到原始开发人员遇到了循环依赖问题,但从我的谷歌搜索来看,这似乎是合适的解决方案:

//workaround for circular dependency
@Autowired
public void setAssessmentService(AssessmentService assessmentService) {
   this.assessmentService = assessmentService;
}

// to prevent circular dependency problem ...
@Autowired 
public void setDocumentService(DocumentService documentService) {
    this.documentService = documentService;
}

标签: javaspring-bootdependency-injection

解决方案


错误消息指出,在创建 bean 时,它的数据源有问题:

InvalidDataAccessResourceUsageException:无法提取 ResultSet

我怀疑读取数据库时出现问题。不存在循环依赖问题。这是一个完美的创豆链。Spring 检测到循环依赖并显示不同的错误消息。

尝试取消注释 @PostConstruct 中的代码并再次运行应用程序。

@PostConstruct
public void postConstruct() {
    for (QuestionType type : QuestionType.values()) {
        numberOfQuestionsByType.put(type, 
           questionService.findByQuestionType(type).size());
    }
}

推荐阅读