Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

spring autowired aop circular dependency

I'm using java config with @ComponentScanin order to initialize my beans and @EnableAspectJAutoProxy(proxyTargetClass=true)to use cglib proxies.

In this project we have a lots of generated services autowired between them using @Autowired. It works pretty well.

But, for some of these services I've added @Async (I've also added @EnableAsync(proxyTargetClass = true)on my @Configurationclass).

After that, I'm getting:

Caused by: org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name 'ConversationUserLocalService': Bean with name 'ConversationUserLocalService' has been injected into other beans [ConversationUserHistoryLocalService] i n its raw version as part of a circular reference, but has eventually been wrapped. This means that said other beans do not use the final version of the bean. This is often the result of over-eager type matching - consider using 'getBeanNamesOfType' with the 'a llowEagerInit' flag turned off, for example. 

I guess this is because Spring is injecting the service with @Asyncmethod BEFORE AOP creates the proxy. Could this be the problem? How I should fix it?

In order to try to clarify my problem, let's say I have:

@Service A, B & C;

A has autowired B & C, B has autowired A & C, C has autowired A & B;

C has a method marked as @Async.

When Spring initialize applicationContext, it tries to initialize A, but needs B & C, so it initializes them. But after all, AOP tries to make a proxy of C (because @Async) and then it detects that autowired C into B and A is not the same as proxy of C so it fails.

I hope this can explain a little more what is happening.

like image 476
ilopezluna Avatar asked Mar 11 '15 11:03

ilopezluna


People also ask

Can Spring handle circular dependency?

But with a circular dependency, Spring cannot decide which of the beans should be created first since they depend on one another. In these cases, Spring will raise a BeanCurrentlyInCreationException while loading context. It can happen in Spring when using constructor injection.

How do I fix circular dependency?

To resolve circular dependencies: Then there are three strategies you can use: Look for small pieces of code that can be moved from one project to the other. Look for code that both libraries depend on and move that code into a new shared library. Combine projectA and projectB into one library.

How do you avoid circular dependencies?

Avoiding circular dependencies by refactoring Circular dependencies create tight couplings between the classes or modules involved, which means both classes or modules have to be recompiled every time either of them is changed.

How do you break cyclic dependency?

To remove the cycle using DI, we remove one direction of the two dependencies and harden the other one. To do that we should use an abstraction: in the order module, we add the DiscountCalculator interface. Thus, the Order class depends on this new type and the order module no longer depends on the customer module.


2 Answers

Finally I sorted it out using @Lazyon services (with methods annotated with @Async), and also, where they were autowired. This way I guess Spring only initialize and autowires those services when they're required instead of on application context initialization.

like image 61
ilopezluna Avatar answered Sep 24 '22 09:09

ilopezluna


I have same issue and I solved this issue:

  1. I identified which @Autowired property is reason for circular dependency.

    Eg:

    @Autowired private TestService testService; 

    (Tips to identified just try to comment and find out which property is reason to break the application)

  2. Once identified just use @Lazy on top of this @Autowired variable.

    Eg :

    @Lazy @Autowired private TestService testService; 

    And Application worked smoothly.

like image 32
Vikash Singh Avatar answered Sep 22 '22 09:09

Vikash Singh