服务循环引用有多糟糕?

How bad is a service circular reference?

我有一个问题,它与我遇到的错误有关。在我的服务中使用循环引用到底有多糟糕?我很清楚错误的原因以及如何解决它,只是在我工作的公司中,一位资深人士建议我,对于交易问题,有必要进行这样的循环引用,实际上这是一个非常经常发生的问题在那里练习,但由于我是从头开始一个个人项目,这是我第一次得到错误,它再次引发了疑问。非常感谢您!

这是服务的代码

public class MedicalRecordServiceImpl implements MedicalRecordService {

    private final MedicalRecordRepository medicalRecordRepository;
    private final MedicalRecordService medicalRecordService;
    private final PatientService patientService;
    private final TutorService tutorService;
    private final MedicalHistoryAnswerService medicalHistoryAnswerService;
    private final DentalHistoryAnswerService dentalHistoryAnswerService;

    public MedicalRecordServiceImpl(MedicalRecordRepository medicalRecordRepository, MedicalRecordService medicalRecordService, PatientService patientService, TutorService tutorService, MedicalHistoryAnswerService medicalHistoryAnswerService, DentalHistoryAnswerService dentalHistoryAnswerService) {
        this.medicalRecordRepository = medicalRecordRepository;
        this.medicalRecordService = medicalRecordService;

        this.patientService = patientService;
        this.tutorService = tutorService;
        this.medicalHistoryAnswerService = medicalHistoryAnswerService;
        this.dentalHistoryAnswerService = dentalHistoryAnswerService;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void saveMedicalRecord(MedicalRecordEntity medicalRecord) {
        medicalRecordRepository.save(medicalRecord);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public ResponseEntity<?> createNewMedicalRecord(MedicalRecordDTO medicalRecordDTO) {

        PatientEntity patient = this.storeMedicalRecordIntoPatient(medicalRecordDTO);
        TutorEntity tutor = this.storeMedicalRecordIntoTutor(medicalRecordDTO);
        List<MedicalHistoryAnswerEntity> medicalHistoryAnswers = this.storeMedicalRecordIntoMedicalHisAns(medicalRecordDTO);
        List<DentalHistoryAnswerEntity> dentalHistoryAnswers = this.storeMedicalRecordIntoDentalHisAns(medicalRecordDTO);

        patientService.savePatient(patient);
        tutor.setPatient(patient);
        tutorService.saveTutor(tutor);

        MedicalRecordEntity medicalRecord = this.createMedicalRecord(patient, tutor);

        medicalRecordService.saveMedicalRecord(medicalRecord);

        medicalHistoryAnswers.forEach(medicalHistoryAnswer -> {
            medicalHistoryAnswer.setMedicalRecord(medicalRecord);
            medicalHistoryAnswerService.saveMedicalHistoryAnswer(medicalHistoryAnswer);
        });

        dentalHistoryAnswers.forEach(dentalHistoryAnswer -> {
            dentalHistoryAnswer.setMedicalRecord(medicalRecord);
            dentalHistoryAnswerService.saveDentalHistoryAnswer(dentalHistoryAnswer);
        });

        return ResponseEntity.status(HttpStatus.OK).body("");
    }
}

如您所说,我假设您知道错误是什么以及如何解决它。循环引用是错误的,原因如下:

Spring 在您启动项目时加载 beans,这意味着它以正确的顺序加载每个 bean,因此它可以加载所有 beans 并成功引用它们。如果你有一个循环引用 Spring 将不知道首先启动哪个 bean,因此会发生错误。这是关于 Spring 的工作原理。

我现在的项目也有这个错误,你不限于不做循环引用,你只需要指示Spring,这样它就知道在这些情况下如何处理每个bean。

好吧,想象一下: 你得到一个新的phone,你都为之兴奋。你想解锁它,但它受密码保护。密码在锁定的phone.

里面的笔记里面有

所以,您想使用您的 phone,为此您需要通行证。你想要通行证,为此你需要解锁 phone。您想使用您的phone,为此您需要您的通行证...等等

当你有循环引用时也会发生同样的情况,A你需要B,B你需要A,所以你不能创建A,也不能创建B,无法继续。

您可能需要循环依赖的唯一原因是您需要访问“this”作为 bean 以触发带注释的方法逻辑。

例如,如果您有两个方法“foo”(用@Transactional 注释)和“bar”(在其中调用“foo”)。如果调用 bar>foo (selfBean.foo() 而不是 this.foo()).

,您将不得不使用自我注入来触发事务

也可以使用@Lasy进行自注入,避免循环依赖错误。

但这是一个非常丑陋的解决方案,您应该尽可能避免使用它。这取决于情况,也许可以将逻辑拆分到不同的服务或使用 TransactionTemplate。