В своем проекте я пытаюсь перенести все использование
Foo foo = (Foo) beanFactory.getBean("name");
в
Foo foo = beanFactory.getBean(Foo.class);
Преимущества очевидны: безопасность типов, менее запутанный код, меньше бесполезных констант и т. д. Обычно такие строки находятся в статических контекстах наследия, где такая проводка является единственным вариантом.
Все это было прекрасно, пока однажды пользователи не начали жаловаться на медлительность, которая, как оказалось, исходила от внутренних компонентов Spring. Поэтому я запустил профайлер, чтобы найти "горячую точку" в
org.springframework.beans.factory.support.AbstractBeanFactory::doGetBean(String, Class
которая имеет дорогой вызов
Class.isAssignableFrom(anotherClass)
.
Я быстро создал небольшой тест производительности, чтобы выяснить, что разница в скорости между поиском имени строки и типа составляет 350 раз (я использую StaticApplicationContext
для этого теста FAIW)!
Исследуя это, я обнаружил SPR-6870, который имеет большое количество голосов, но по какой-то причине не рассматривается. Это привело меня к попытке решить эту проблему, которая значительно улучшает ситуацию, но все еще медленнее ~25 раз, чем поиск по строке! Оказывается, эта попытка решает только половину проблемы: она кэширует имя боба, чтобы сэкономить на O(n) итерациях, но все равно приходится делать вызов isAssignableFrom
для проверки типа.
Описанная проблема относится не только к моему сценарию, но и к бобам, использующим @Autowired
, и может быть ощутима в случаях, когда бобы создаются внутри цикла.
Одним из решений может быть переопределение одного из методов фабрики бобов и кэширование результатов проверки is-this-bean-of-the-same-type, но очевидно, что это должно быть сделано в Spring, а не в моем собственном коде.
Кто-нибудь еще страдает от подобной проблемы и нашел ее решение?