Spring wiring by type is slower by magnitude than wiring by name

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

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

в

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

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

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

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

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

Class.isAssignableFrom(anotherClass).

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

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

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

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

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

24
задан mindas 24 February 2012 в 11:34
поделиться