views:

28

answers:

2

I have a couple of beans defined with java @Configuration. Some of them have methods perform pretty long calculations and I'd like to cache returned values for given arguments to avoid making those calculations every time a method is called.

Example:

@Configuration public class Config {
    @Bean public CalculatorBean calcBean() {
        return new CalculatorBean();
    }
}

public class CalculatorBean {
    public int hugeCalculation(int arg1, String arg2, double[] arg3) {
        // ... very long calculation ...
    }
}

Ideally, I'd like to annotate @Bean methods in @Configuration with some kind of custom @Cached(method="hugeCalculation", size=1000, ttl=36000) and have bean factory automatically post-processed to wrap those beans in AOP proxies.

Are there any ready solutions of this kind? If not, what classes of Spring should I use to do this?

+2  A: 

If the values really are constant, how about turning CalculatorBean into a FactoryBean instead? I'm not exactly sure how this would work with your @Configuration -- I've never used that annotation.

You could return (for example) an Integer.class, make it a singleton, and then do the calculations in the getObject method. Something like the following:

public class CalculatorBean implements FactoryBean {
    public Object getObject() {
        return (Integer)hugeCalculation(...);
    }
    public Class getObjectType() {
        return Integer.class;
    }
    public boolean isSingleton() {
        return true;
    }
    private int hugeCalculation(int arg1, String arg2, double[] arg3) {
        // ... very long calculation ...
    }
}
Gray
No, they are not constant, but I can trade freshness for performance in this case.
Shooshpanchick
A: 

In the end I ended up using Ehcache, but before that I created a following solution:

  1. I created a BeanPostProcessor that retrieved BeanDefinition from the bean (doesn't matter before or after initialization).
  2. From that BeanDefinition via getSource() I retrieved MethodMetadata of the @Bean-annotated method of that bean.
  3. From that MethodMetadata I retrieved method's annotations.
  4. If they contained my custom @Cached annotation, I wrapped that bean in a MethodInterceptor that cached method result in the way I needed.

Anyway, Ehcache is a better solution, and it has spring integration too, though it requires annotating actual methods that need to be cached. This means that you cannot cache calls selectively, but for most purposes it is not needed.

Shooshpanchick