Hi,
Sorry, I am new to spring and new to this forum. Feel free to criticize anything.
I am using spring 3.0.5.
My overall issue is that I need to instantiate numerous (Let's say dozens or hundreds of thousands) prototype beans from several singleton beans. I don't know the instantiation count at application startup. The application need to be very fast (But should rely on spring).
In the following code, the singleton bean "Foo" need to create "count" of "MyBean" when its "perform" method is called.
Three different ways are used to create the "MyBean" instances.
1/ Using beanFactory.getBean(String). "FooImpl" implements BeanFactoryAware so it can use it to retrieve an instance by name.
2/ Using beanFactory.getBean(Class). Instead of using the bean name, the class is used.
3/ Using myBeanFactory.getObject(). An ObjectFactory<MyBean> is injected using @Autowired. So it is used to create instances.
It is written in several places on the web that getBean(String) is not supposed to be very fast. It is even in the old javadoc.Code:@Configuration public class MyConfiguration { @Bean public Foo foo() { return new FooImpl(); } @Bean @Scope("prototype") public MyBean myBean() { return new MyBeanImpl(); } } public class FooImpl implements Foo, BeanFactoryAware { @Autowired private ObjectFactory<MyBean> myBeanFactory; private BeanFactory beanFactory; public void perform(int count) { SimpleChrono chrono1 = new SimpleChrono("BeanFactory, by name"); for (int i = 0; i < count; i++) { MyBean myBean = (MyBean)beanFactory.getBean("myBean"); } chrono1.stop(); SimpleChrono chrono2 = new SimpleChrono("BeanFactory, by class"); for (int i = 0; i < count; i++) { MyBean myBean = (MyBean)beanFactory.getBean(MyBean.class); } chrono2.stop(); SimpleChrono chrono3 = new SimpleChrono("ObjectFactory"); for (int i = 0; i < count; i++) { MyBean myBean = myBeanFactory.getObject(); } chrono3.stop(); } @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; } }
I thought it would be a difficult task for getBean(String) to find the corresponding class to instantiate basing on the configuration field name.Note that callers should retain references to returned objects. There is no guarantee that this method will be implemented to be efficient. For example, it may be synchronized, or may need to run an RDBMS query.
I thought that getBean(Class) would be faster.
And I thought that the dedicated factory would be far more faster. Because it is dedicated. The needed class is known at compilation time, the factory has to provide instances of a single class... The first getObject() could be slow, but others would be damn fast.
I was all wrong. Here are the results (For count = 10000):
getBean(String) is twelve times faster than others methods...12/01/12 18:06:47 DEBUG Starting 'BeanFactory, by name'.
12/01/12 18:06:48 DEBUG End of 'BeanFactory, by name' 00:00:01:125
12/01/12 18:06:48 DEBUG Starting 'BeanFactory, by class'.
12/01/12 18:07:08 DEBUG End of 'BeanFactory, by class' 00:00:20:187
12/01/12 18:07:08 DEBUG Starting 'ObjectFactory'.
12/01/12 18:07:29 DEBUG End of 'ObjectFactory' 00:00:20:516
Why the hell?
Here is profiler screenshot for getObject.
The method 3 with a dedicated factory seems really cleaner to me. But due to performance issue, I will have do use getbean(String)?
MyBean could be a classical java class, not used as a bean with spring dependency injection. So I would have to manually give to MyBean its dependency. What are the others drawbacks with this solution ?
Is there others ways to solve this problem?



Reply With Quote
