In my project, I am trying to migrate all usages of
Foo foo = (Foo) beanFactory.getBean("name");
into
Foo foo = beanFactory.getBean(Foo.class);
The benefits are obvious: type safety, less convoluted code, less useless constants, etc. Typically such lines are located in static legacy contexts where such a wiring is the only option.
This was all fine until one day users started to complain about the slowness which turned out to come from Spring internals. So I fired up a profiler to find a hotspot in
org.springframework.beans.factory.support.AbstractBeanFactory::doGetBean(String, Class<T>, Object[], boolean)
which has an expensive call to
Class.isAssignableFrom(anotherClass)
.
I have quickly created a small performance test to find out the speed difference between string name and type lookups is a whooping 350 times (I'm using StaticApplicationContext
for this test FAIW)!
While investigating this, I found SPR-6870 which has high number of votes but for some reason isn't addressed. This led me to an attempt to solve this problem which does significantly improve the situation but is still slower ~25 times than lookup by String! It turns out this attempt only solves half of the problem: it caches the name of the bean to save on O(n) iteration but still has to do call isAssignableFrom
to validate the type.
Described problem is not only related to my scenario but is also for beans which use @Autowired
and can be felt hard in cases where beans are created inside a loop.
One of solutions would be to override one of the bean factory methods and cache the is-this-bean-of-the-same-type check results but clearly this should be done in Spring and not in my own code.
Is anyone else suffering from a similar problem and found a solution to it?