Search code examples
javaspringconfigurableaspect

Alternative to Spring's @Configurable for performance reasons?


I am using @Configurable beans for non-managed spring instances in a section of code that must be highly performant. We are using a lot of non-managed beans with the new operator, and in our profiling we have noticed that the use of the @Configurable annotation is slowing things down quite a bit.

Just for this specific section, we would like a faster way of pulling beans from the context (just a direct applicationContext.getBean()). I know we give up IoC doing this, but this is a special scenario and not a normal pattern.

We are using CTW for the weaving, but I wanted to know what mechanism spring is using behind the scenes to get the application context so we can simply grab it and use getBean? A static application context? Is it stored in threadlocal somewhere?


Solution

  • Aspects are singletons managed by AspectJ. When you put an aspect in your Spring configuration file Spring doesn't actually create the aspect. Instead it obtains a reference to the aspect using aspectOf().

    This means that (at compile time when you do your weaving) your @Configurable annotation gets hooked into the singleton AnnotationBeanConfigurerAspect. Then when you load your application context, Spring obtains a reference to that same singleton aspect and calls the setBeanFactory() method on the aspect (since it implements BeanFactoryAware).

    This magic can lead to trouble of course. If you had two application contexts then the second would overwrite the configuration of the first which can be terribly confusing.

    To answer your question directly this means that all you have to do is create a new aspect that implements BeanFactoryAware (here is the code for AnnotationBeanConfigurerAspect which you can use as an example) and then "instantiate" that same aspect in your spring configuration file and your aspect will now have access to the bean factory.

    If you're going for performance then please note that the above is not much cleaner than creating a static reference to the BeanFactory and instantiating that when you start your application so you might as well do the static reference as it is simpler.