Автопрокси AspectJ не работает с GigaSpaces 8 и Spring 3, потому что класс загружается другим загрузчиком классов - PullRequest
1 голос
/ 19 февраля 2020

Мы используем GigaSpaces версии 8.0.0 (да, она старая) и Spring 3 (да, она также старая). Существует два модуля A и B. A - это «основной» модуль, который читает и пишет в пространство и предоставляет некоторые удаленные службы. А и Б работают отдельно. B создает экземпляр объекта, который имеет поле, являющееся объектом класса. Этот класс существует только в B; А не знает об этом. Затем он выполняет удаленный вызов A, который завершает запись экземпляра в пространство.

Позже A загружает эту сущность и создает экземпляр удаленного класса, выполняя entity.getClassObject().newInstance(). Это работает, даже если этот класс не существует в загрузчике классов времени выполнения A, поскольку загрузчик классов для этого класса является загрузчиком классов LRMI (легкий вызов удаленного метода), который поставляется с GigaSpaces. Я думаю, он знает, как создать его экземпляр.

Проблема возникла, когда мы добавили аспект к A. У нас есть существующий код, который автоматически связывает экземпляр удаленного класса с использованием контекста приложения A, а также инициализирует его с помощью initializeBean. Автопроводка и инициализация работали нормально, пока мы не добавили аспект. Теперь, во время инициализации, он пытается увидеть, применимы ли советы в аспекте к компоненту, который инициализируется. В рамках этого процесса он пытается создать экземпляр класса, используя Class.forName и имя класса компонента. Это приводит к ClassNotFoundException, потому что класс, очевидно, не существует в загрузчике класса времени выполнения. Поэтому AspectJ разрешает тип как MissingResolvedTypeWithKnownSignature вместо немедленного сбоя. Но в конечном итоге происходит сбой, когда AspectJ пытается найти суперкласс класса, потому что у него нет этой информации, и он выдает следующее исключение:

org.aspectj.weaver.reflect.ReflectionWorld$ReflectionWorldException: warning can't determine implemented interfaces of missing type com.mypackage.MyRemoteClass
 [Xlint:cantFindType]
        at org.aspectj.weaver.reflect.ReflectionWorld$ExceptionBasedMessageHandler.handleMessage(ReflectionWorld.java:129)
        at org.aspectj.weaver.Lint$Kind.signal(Lint.java:328)
        at org.aspectj.weaver.MissingResolvedTypeWithKnownSignature.raiseCantFindType(MissingResolvedTypeWithKnownSignature.java:232)
        at org.aspectj.weaver.MissingResolvedTypeWithKnownSignature.getDeclaredInterfaces(MissingResolvedTypeWithKnownSignature.java:86)
        at org.aspectj.weaver.ResolvedType.getDirectSupertypes(ResolvedType.java:82)
        at org.aspectj.weaver.patterns.TypePattern.matchesSubtypes(TypePattern.java:178)
        at org.aspectj.weaver.patterns.ExactTypePattern.matchesSubtypes(ExactTypePattern.java:74)
        at org.aspectj.weaver.patterns.TypePattern.matchesStatically(TypePattern.java:130)
        at org.aspectj.weaver.patterns.KindedPointcut.fastMatch(KindedPointcut.java:141)
        at org.aspectj.weaver.internal.tools.PointcutExpressionImpl.couldMatchJoinPointsInType(PointcutExpressionImpl.java:84)
        at org.springframework.aop.aspectj.AspectJExpressionPointcut.matches(AspectJExpressionPointcut.java:238)
        at org.springframework.aop.support.AopUtils.canApply(AopUtils.java:200)
        at org.springframework.aop.support.AopUtils.canApply(AopUtils.java:254)
        at org.springframework.aop.support.AopUtils.findAdvisorsThatCanApply(AopUtils.java:286)
        at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findAdvisorsThatCanApply(AbstractAdvisorAutoProxyCreator.java:117)
        at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.findEligibleAdvisors(AbstractAdvisorAutoProxyCreator.java:87)
        at org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator.getAdvicesAndAdvisorsForBean(AbstractAdvisorAutoProxyCreator.java:68)
        at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:359)
        at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:322)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsAfterInitialization(AbstractAutowireCapableBeanFactory.java:407)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1426)
        at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:386)
...

Есть ли способ обойти это? Я могу придумать два подхода, но я не совсем уверен, как это сделать. Один из них заключается в том, чтобы как-то запретить Spring проверять, применим ли аспект, а другой, возможно, состоит в том, чтобы заменить загрузчик классов времени выполнения на тот, который делегирует загрузчику классов LRMI, если он не может найти класс в загрузчике классов времени выполнения. Но я не уверен, смогу ли я получить экземпляр загрузчика классов LRMI.

Кто-нибудь сталкивался с такой проблемой?

1 Ответ

1 голос
/ 20 февраля 2020

Это известная проблема в версии AspectJ, которую я использовал (1.6.12). Похоже, что это было исправлено в более поздних версиях - по крайней мере, начиная с 1.8.14 (что я и обновил). Обновление моей версии AspectJ устранило эту проблему.

...