Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

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?

like image 867
mindas Avatar asked Feb 24 '12 11:02

mindas


People also ask

How many types of wires are there in Spring?

In Spring, 5 Auto-wiring modes are supported. byName – Auto wiring by property name. If the name of a bean is same as the name of other bean property, auto wire it.

What is the different wiring used by Spring container?

So, Spring is able to utilize the BeanFactory to know the dependencies across all the used beans. The XML-configuration-based autowiring functionality has five modes – no , byName , byType , constructor , and autodetect .

What is true about @autowired annotation?

The @Autowired annotation provides more fine-grained control over where and how autowiring should be accomplished. The @Autowired annotation can be used to autowire bean on the setter method just like @Required annotation, constructor, a property or methods with arbitrary names and/or multiple arguments.

What is the default wiring used by Spring container?

The default mode of Spring's traditional XML-based configuration is 'no' i.e no auto wiring is enabled by default. But, if you choose to use annotation-based configuration(<context:annotation-config>), & for instance, if you are using @Autowired , then the default method of auto wiring for this is "byType".


1 Answers

This problem is now solved in Spring with the resolution of SPR-6870. See the resolution comments there for details. The fix is available as of versions 3.2.0.RELEASE and 3.1.2.

like image 167
Chris Beams Avatar answered Sep 21 '22 21:09

Chris Beams