Подтвердить что ты не робот

Spring проводка по типу медленнее по величине, чем проводка по названию

В моем проекте, я пытаюсь перенести все использования

Foo foo = (Foo) beanFactory.getBean("name");

в

Foo foo = beanFactory.getBean(Foo.class);

Преимущества очевидны: тип безопасности, менее свернутый код, менее бесполезные константы и т.д. Обычно такие строки находятся в статических устаревших контекстах, где такая проводка является единственным вариантом.

Все было в порядке до одного дня, когда пользователи начали жаловаться на медленность, которая, как оказалось, появилась из Spring внутренних. Поэтому я запустил профайлер, чтобы найти горячую точку в

org.springframework.beans.factory.support.AbstractBeanFactory::doGetBean(String, Class<T>, Object[], boolean)

который имеет дорогой вызов

Class.isAssignableFrom(anotherClass).

Я быстро создал небольшой тест производительности, чтобы узнать разницу в скорости между строковым именем и поиском типов - это критический 350 раз (я использую StaticApplicationContext для этого теста FAIW)!

При исследовании этого вопроса я нашел SPR-6870, который имеет большое количество голосов, но по какой-то причине не рассматривается. Это привело меня к попытке решить эту проблему, которая значительно улучшает ситуацию, но все еще медленнее ~ 25 раз, чем поиск по String! Оказывается, эта попытка решает только половину проблемы: она кэширует имя bean для сохранения в O (n) итерации, но все же необходимо выполнить вызов isAssignableFrom для проверки типа.

Описанная проблема связана не только с моим сценарием, но также и с beans, которые используют @Autowired и могут ощущаться в тех случаях, когда beans создаются внутри цикла.

Одним из решений было бы переопределить один из методов bean factory и кэшировать результаты проверки is-this- bean -of-the-same-type, но ясно, что это должно быть сделано в Spring а не в моем собственном коде.

Кто-нибудь еще страдает от подобной проблемы и нашел решение?

4b9b3361

Ответ 1

Эта проблема теперь решена в Spring с разрешением SPR-6870. См. Комментарии к комментариям для получения подробной информации. Исправление доступно в версиях 3.2.0.RELEASE и 3.1.2.

Ответ 2

Большинство приложений Spring соединяются при запуске, а не захватывают beans из контекста во время выполнения. Даже если вы не изменяете свой контекст приложения во время обычной работы вашего приложения, вы никогда не должны извлекать bean более одного раза.

Учитывая, что если ваши пользователи жалуются на медлительность, кажется, что ваша настоящая проблема - слишком много поисков bean; ваше использование более медленных средств для этого просто отразилось на реальной проблеме.

Я бы попытался перейти к Java Config (настроить свои зависимости в Java, поддерживаемый в Spring 3.0, я полагаю) и настроить приложение для подключения всех beans при запуске. Это также имеет то преимущество, что ваше приложение просто не запускается, если зависимости не могут быть выполнены.