Сначала урезанный вид моей иерархии классов:
@Entitypublic class Config {
// поля и прочее
}
public интерфейс Exporter {
int startExport() бросает ExporterException;
void setConfig(Config config);
}
публичный абстрактный класс ExporterImpl реализует Exporter {
защищенную конфигурацию конфигурации;
@Override
public Final void setConfig(Config config) {
this.config = config;
// this.config является допустимым экземпляром конфигурации здесь
/>
@Override
@Transactional(readOnly = true)
public int startExport() бросает ExporterException {
// this.config здесь имеет значение NULL
/>
// другие методы, включая абстрактный для подкласса
}
@Scope("prototype")
@Service("cars2Exporter")
публичный класс Cars2ExporterImpl расширяет ExporterImpl {
// переопределяем абстрактные методы и некоторые другие
// не трогаем startExport()
}
// есть другие реализации ExporterImpl тоже
// во всех реализациях возникает проблема
код вызова такой:
@Inject
частный поставщик cars2Exporter;
public void ScheduleExport(Config config) {
Exporter Exporter = cars2Exporter.get();
Exporter.setConfig(config);
Exporter.startExport();
// на самом деле я обертываю это здесь в класс, реализующий runnable
// и помещаю его в очередь ` TaskExecutor`, но проблема возникает
// и при прямом вызове.
В чем именно проблема?
В вызове startExport() поле config ExporterImpl имеет значение null, хотя оно было установлено прямо перед этим.
Что я нашел на данный момент:
С точкой останова в экспортере. startExport(); Я проверил идентификатор экземпляра экспортера, показанный отладчиком eclipse, во время написания этого поста это 16585. Продолжаем выполнение в вызове/первой строке startExport() где я еще раз проверил идентификатор (на этот раз), ожидая, что он будет таким же, но понимая, что это не так. Здесь это 16606... поэтому вызов startExport(). выполняется для другого экземпляра класса... в предыдущем раунде отладки я проверил, к какому экземпляру/идентификатору относится вызов setConfig()... к первому (16585 в этом case). Это объясняет, почему поле конфигурации в экземпляре 16606 имеет значение null.
Чтобы понять, что происходит между строкой, в которой я вызываю Exporter.startExport();, и фактическим значением. первую строку startExport() Я щелкнул шаги между этими обеими строками в отладчике eclipse.
Там я дошел до строки 655 в CglibAopProxy, которая выглядит следующим образом:
retVal = new CglibMethodInfection(proxy, target, метод, args, targetClass, Chain, MethodProxy).proceed();
проверка аргументов здесь я обнаружил, что прокси — это экземпляр с идентификатором 16585, а целевой — экземпляр с 16606.
к сожалению, я не так уж глубоко разбираюсь в вещах, которые нужно знать если так и должно быть...
Мне просто интересно, почему есть два экземпляра, которые вызываются разными методами. вызов setConfig() переходит к экземпляру прокси, а вызов do startExport() достигает целевого экземпляра и, следовательно, не имеет доступа к ранее установленной конфигурации...
Как уже упоминалось, проект был перенесен на Spring Boot, но раньше мы уже использовали версию Athens-RELEASE Spring Platform bom. Насколько я могу судить, там не было никаких специальных конфигураций AOP перед миграцией и никаких явно заданных значений после миграции.
Чтобы решить эту проблему (или хотя бы как-то работать), я уже попробовал несколько вещи:
- удалить @Scope из подкласса
- переместить @Transactional с уровня метода в класс
- переопределить startExport() в подклассе и поместить сюда @Transactional
- добавить @EnableAspectJAutoProxy в класс приложения (я даже не смог войти в систему — нет сообщения об ошибке)
- установите для Spring.aop.proxy-target-class значение true
- вышеупомянутое в разных комбинациях...
Заранее спасибо
*надеется, что кто-нибудь сможет помочь*
Подробнее здесь: https://stackoverflow.com/questions/406 ... y-instance
Мобильная версия