Круговая зависимость
Я использую Java-конфиг с @ComponentScan
для того, чтобы инициализировать мои бобы и @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
Метод ДО АОП создает прокси. Это может быть проблемой? Как мне это исправить?
Чтобы попытаться прояснить мою проблему, скажем, у меня есть:
@ Сервис 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, поэтому он терпит неудачу.
Я надеюсь, что это может объяснить немного больше, что происходит.
2 ответа
Наконец я разобрался с помощью @Lazy
на услуги (с методами, аннотированными с @Async
), а также, где они были подключены. Таким образом, я полагаю, что Spring инициализирует и автоматически подключает эти службы только тогда, когда они требуются, а не при инициализации контекста приложения.
У меня такая же проблема, и я решил эту проблему:
Я определил, какие
@Autowired
свойство является причиной круговой зависимости.Например:
@Autowired private TestService testService;
(Подсказки для выявления просто попробуйте прокомментировать и выяснить, какое свойство является причиной поломки приложения)
После определения просто используйте
@Lazy
на вершине этого@Autowired
переменная.Например:
@Lazy @Autowired private TestService testService;
И приложение работало без сбоев.
Классы конфигурации AsyncConfigurer инициализируются на ранних этапах начальной загрузки контекста приложения. Если вам нужны какие-либо зависимости от других bean-компонентов, убедитесь, что они объявлены как "ленивые", насколько это возможно, чтобы позволить им проходить и через другие постпроцессоры.
Ссылка на JavaDoc: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/scheduling/annotation/EnableAsync.html
Мне удалось исправить подобную проблему, добавив @Qualifier вместе с @Autowire, например:
@Autowired
@Qualifier("publisher")
private Publisher publisher;