В моем проекте, я пытаюсь перенести все использования
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 а не в моем собственном коде.
Кто-нибудь еще страдает от подобной проблемы и нашел решение?