В моем проекте я пытаюсь перенести все случаи использования
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
для проверки типа.
Описанная проблемане только относится к моему сценарию, но также и к bean-компонентам, которые используют @Autowired
и могут быть затруднены в случаях, когда bean-компоненты создаются внутри цикла.
Одним из решений будет переопределение одного из методов фабрики bean-компонентови кешировать результаты проверки типа «это бин того же типа», но ясно, что это должно быть сделано в Spring, а не в моем собственном коде.
Кто-то еще страдает от подобной проблемы и обнаружилрешение для этого?