Relying upon circular references is discouraged and they are prohibited by default

내부 메서드 호출에 대해서도 프록시 적용을 위해 setter를 통한 자기 자신 주입을 적용하려는데 아래와 같은 에러 메시지가 발생했습니다.

스프링 부트 2.6.X부터는 기본적으로 순환 참조를 금지하도록 변경되었습니다.

GitHub - spring-projects/spring-boot: Spring Boot

Spring Boot. Contribute to spring-projects/spring-boot development by creating an account on GitHub.

github.com

application.properties 혹은 application.yml에 아래와 같이 설정해주면 순환 참조가 허용됩니다.

강의는 스프링 2.5버전대지만 현재 스프링 이니셜라이저에서 기본 지정 버전은 2.6버전입니다.

여기서는 CallServiceV1에서 사용한 setter에 @Autowired 붙이는 문법을 사용 할 시에는 생성자로 주입할 때랑 똑같이 순환참조냐고 묻는 오류가 발생하더라구요.

혹시나 싶어서 2.5.6으로 해보니 잘 되더랍니다...ㅠㅠ

갑자기 2.6.0버전부터 무슨 일이 생긴지는 모르겠지만 여기서는 안되네요 ㅠㅠ

1, Preface

SpringBoot 2.6.x does not recommend the use of circular dependency, which is good news. Springboot gradually guides developers to write standard code from the bottom. At the same time, it is also sad news. The application scenarios of circular dependency are too wide.

If you upgrade from a lower version to 2.6 x. Then the first problem encountered by a large probability is the circular dependency problem.

2, Problem recovery

1. Code description

The following styles of code are common: both classes have the need to call each other's methods, so it is easy to write circular references.

@Service public class TbDeptServiceImpl extends ServiceImpl<TbDeptMapper, TbDept> implements ITbDeptService {        @Autowired    private ITbStaffService staffService; }
@Service public class TbStaffServiceImpl extends ServiceImpl<TbStaffMapper, TbStaff> implements ITbStaffService {    @Autowired    private ITbDeptService deptService; }
2. Error example
Relying upon circular references is discouraged and they are prohibited by default. Update your application to remove the dependency cycle between beans. As a last resort, it may be possible to break the cycle automatically by setting spring.main.allow-circular-references to true.
Despite circular references being allowed, the dependency cycle between beans could not be broken. Update your application to remove the dependency cycle.

3, Problem solving

1. Rough settlement

The simplest way is to allow circular reference in the global configuration file. The default value of this property is false, and the display declaration is true, which can avoid the console circular reference exception when the project is started.

spring: main:   allow-circular-references: true
2. Elegant solution

Spring officially prohibits the use of circular dependencies by default, although there are optional configurations that allow developers to continue to use circular dependencies.

Spring's official intention is that it doesn't want developers to write code with circular dependency. That is to say, it may be forced not to use circular dependency in a future version. Therefore, we have to face the problem of gradually eliminating circular dependency in new projects.

Use the return value of the method to obtain the instance object, and replace the instance object injected through the member variable.

@Service public class TbDeptServiceImpl extends ServiceImpl<TbDeptMapper, TbDept> implements ITbDeptService {    /**     * Use the method to return the instance object and replace the member variable injection     * @return ITbStaffService     */    public ITbStaffService getStaffService(){        return SpringUtils.getBean(ITbStaffService.class);   } }
@Service public class TbStaffServiceImpl extends ServiceImpl<TbStaffMapper, TbStaff> implements ITbStaffService {    /**     * Use the method to return the instance object and replace the member variable injection     * @return ITbStaffService     */    public ITbDeptService getDeptService(){        return SpringUtils.getBean(ITbDeptService.class);   } }

The following dependencies need to be used. This dependency is a public dependency extracted by the author and can be used across projects.

<dependency>    <groupId>xin.altitude.cms.common</groupId>    <artifactId>ucode-cms-common</artifactId>    <version>1.3.4</version> </dependency>

If this dependency cannot be found, it is likely that Alibaba cloud Maven warehouse has not been synchronized yet. It is enough to force the use of Maven central warehouse in the project.

<repositories> <repository> <id>public</id> <name>maven nexus</name> <url>https://repo1.maven.org/maven2/</url> <snapshots> <updatePolicy>always</updatePolicy> </snapshots> </repository> </repositories>

4, Summary

As a widely used framework, Spring ecology has become the mainstream standard of Java enterprise applications. Its small changes have an immeasurable impact on the integration ecology. From follower to guide, we resolutely prohibit the problem of circular dependence, which reflects the responsibility as a guide.

I'm used to using circular references. It seems that the code is OK at first. It's unreasonable to think about it carefully. The direct expression of circular dependency is that you have me and I have you, which is puzzling from the design of objects.

Most developers always pay attention to the changes of the underlying framework, which will benefit in the application layer. The underlying framework mentioned here refers to JDK, Spring ecology, Apache, well-known big manufacturers' open source and widely used frameworks, such as guava.

Is it okay to have circular references?

Circular references aren't a bad thing in itself: you can use them to achieve complex calculations that are otherwise impossible to do, but first you must set them up properly.

How do I allow circular references?

Go to the Formulas tab, click the arrow next to Error Checking, and point to Circular References The last entered circular reference is displayed there. Click on the cell listed under Circular References, and Excel will bring you exactly to that cell.

What is circular reference in spring boot?

Circular dependency in Spring happens when two or more beans require instance of each other through constructor dependency injections. For example: There is a ClassA that requires an instance of ClassB through constructor injection and ClassB requires an instance of class A through constructor injection.