SpringBoot2.6.x Countermeasures after disabling circular dependency by default

Posted by iversonm on Wed, 23 Feb 2022 02:44:07 +0100

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.