简体   繁体   中英

The dependencies of some of the beans in the application context form a cycle

I'm working on a Spring Boot v1.4.2.RELEASE application with JPA.

I defined repository interfaces and implementations

ARepository

@Repository
public interface ARepository extends CrudRepository<A, String>, ARepositoryCustom, JpaSpecificationExecutor<A> {
}

ARepositoryCustom

@Repository
public interface ARepositoryCustom {
    Page<A> findA(findAForm form, Pageable pageable);
}

ARepositoryImpl

@Repository
public class ARepositoryImpl implements ARepositoryCustom {
    @Autowired
    private ARepository aRepository;
    @Override
    public Page<A> findA(findAForm form, Pageable pageable) {
        return aRepository.findAll(
                where(ASpecs.codeLike(form.getCode()))
                .and(ASpecs.labelLike(form.getLabel()))
                .and(ASpecs.isActive()),
                pageable);
    }
}

And a service AServiceImpl

@Service
public class AServiceImpl implements AService {
    private ARepository aRepository;
    public AServiceImpl(ARepository aRepository) {
        super();
        this.aRepository = aRepository;
    }
    ...
}

My application won't start with the message :

***************************
APPLICATION FAILED TO START
***************************

Description:

The dependencies of some of the beans in the application context form a cycle:

|  aRepositoryImpl
└─────┘

I followed all steps discribed in http://docs.spring.io/spring-data/jpa/docs/current/reference/html/#repositories.single-repository-behaviour

Please help !

Laurent

Use @Lazy

A simple way to break the cycle is by asking Spring to initialize one of the beans lazily. That is: instead of fully initializing the bean, it will create a proxy to inject it into the other bean. The injected bean will only be fully created when it's first needed.

@Service
public class AServiceImpl implements AService {
    private final ARepository aRepository;
    public AServiceImpl(@Lazy ARepository aRepository) {
        super();
        this.aRepository = aRepository;
    }
    ...
}

source: https://www.baeldung.com/circular-dependencies-in-spring

There's a simple fix for your original problem: Just remove @Repository from ARepositoryCustom and from ARepositoryImpl. Keep all the naming and interface/class hierarchies. They are all OK.

I've tested your source code, and found something tricky.

First, with your source code, I got the following error:

There is a circular dependency between 1 beans in the application context:
- ARepositoryImpl (field private test.ARepository test.ARepositoryImpl.aRepository)
- aRepositoryImpl

Then, I guess Spring 'confused' between ARepository (JPA repository) and ARepositoryImpl (Custom repository). So, I would suggest you rename ARepository to something else, such as BRepository . It worked if I renamed the class name.

According to offcial documentation of Spring Data ( https://docs.spring.io/spring-data/jpa/docs/current/reference/html/ ) :

These classes need to follow the naming convention of appending the namespace element's attribute repository-impl-postfix to the found repository interface name. This postfix defaults to Impl

Use @Lazy annotation it will be resolved

@Component
public class Bean1 {
    @Lazy
    @Autowired
    private Bean2 bean2;
}

add this in your pom.xml file. It works for me

spring.main.allow-circular-references:true

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM