Spring автоматическая циркулярная зависимость
Я использую конфигурацию java с @ComponentScan
, чтобы инициализировать мой beans
и @EnableAspectJAutoProxy(proxyTargetClass=true)
для использования прокси-сервера cglib.
В этом проекте у нас есть много сгенерированных сервисов, которые были между ними с помощью @Autowired
. Он работает очень хорошо.
Но для некоторых из этих сервисов я добавил @Async
(я также добавил @EnableAsync(proxyTargetClass = true)
в мой класс @Configuration
).
После этого я получаю:
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.
Я предполагаю, что это потому, что Spring вводит службу с помощью метода @Async
ПЕРЕД AOP создает прокси.
Это может быть проблема?
Как я должен это исправить?
Чтобы попытаться прояснить мою проблему, скажем, у меня есть:
@Service A, B и C
A имеет автообновленные B и C
B имеет автоподвод A и C
C имеет автоуровневые A и B
C имеет метод, помеченный как @Async.
Когда Spring инициализирует applicationContext, он пытается инициализировать A, но ему нужны B и C, поэтому он инициализирует их. Но, в конце концов, AOP пытается сделать прокси-сервер C (потому что @Async), а затем обнаруживает, что автоуровень C в B и A не совпадает с прокси-сервером C, поэтому он терпит неудачу.
Надеюсь, это может объяснить немного больше того, что происходит.
Ответы
Ответ 1
Наконец, я разобрал его с помощью @Lazy
в сервисах (с помощью методов, аннотированных с помощью @Async
), и также, где они были автоматически.
Таким образом, я предполагаю, что Spring инициализирует и автоматически выполняет эти службы, когда они необходимы, а не при инициализации контекста приложения.
Ответ 2
Мне удалось установить аналогичную проблему, добавив @Qualifier вместе с @Autowire, например:
@Autowired
@Qualifier("publisher")
private Publisher publisher;
Ответ 3
Классы конфигурации AsyncConfigurer инициализируются на ранних этапах начальной загрузки контекста приложения. Если вам нужны какие-либо зависимости от других bean-компонентов, убедитесь, что они объявлены как "ленивые", насколько это возможно, чтобы позволить им проходить и через другие постпроцессоры.
Ссылка на JavaDoc: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/scheduling/annotation/EnableAsync.html