В нашем приложении есть несколько (на самом деле много, около 30) веб-сервисов. Каждая веб-служба находится в собственном WAR-файле и имеет собственный контекст Spring, который инициализируется при запуске приложения.
У нас также есть несколько классов аспектов на основе аннотаций, которые мы применяем к классам веб-сервисов. Вначале выражение «указатель» выглядело так:
@Pointcut("execution(public * my.package.service.business.*BusinessServiceImpl.*(..))")
public void methodsToBeLogged() {
}
И AOP был включен для служб через запись в конфигурации.
Но когда количество веб-служб выросло, мы начали испытывать OutOfMemoryException
на наших серверы. После профилирования и анализа выяснилось, что память занимает кеш, который хранится экземплярами класса AspectJExpressionPointcut.
Кэш каждого экземпляра составлял около 5 МБ. И поскольку у нас было 3 аспекта и 30 сервисов, в результате получилось, что 90 экземпляров содержат в общей сложности 450 МБ данных.
После изучения содержимого кэша мы поняли, что он содержит экземпляры метода отражения Java для всех классов, существующих в WAR, даже тех, которые не являются частью пакета my.package.service.business. После изменения выражения сечения точки, чтобы дополнительно включить в предложение
:
@Pointcut("execution(public * my.package.service.business.*BusinessServiceImpl.*(..)) &&
within(my.package.service.business..*)")
public void methodsToBeLogged() {
}
Использование памяти снова снизилось до нормального. И все экземпляры AspectJExpressionPointcut вместе занимали менее 1 МБ.
Может кто-нибудь объяснить, почему это так? И почему выражения среза первой точки недостаточно? Почему кэш AspectJExpressionPointcut
не используется совместно?