Skip to content

AST Based Implementation

Jeff Scott Brown edited this page Oct 26, 2016 · 5 revisions

Version 4.0.0 of the plugin will be the first version of the plugin that rigs up all of the caching behavior at compile time and will not depend on any runtime proxies. The effort is still a work in progress.

Right now if you author a class like this:

import grails.plugin.cache.Cacheable
import groovy.transform.CompileStatic

@CompileStatic
class DemoService {

    @Cacheable('demo')
    def methodOne() {
        42
    }

    @Cacheable(value='demo', key='#argTwo')
    def methodTwo(String argOne, String argTwo) {
        2112
    }

    @Cacheable(value = 'basic', condition='#x < 10')
    def multiply(int x, int y) {
        x * y
    }
}

The compiler will generate a class that looks like this:

public class DemoService {
    @Autowired(
        required = false
    )
    private GrailsCacheKeyGenerator customCacheKeyGenerator;
    @Autowired(
        required = false
    )
    private CacheManager grailsCacheManager;

    @Cacheable({"demo"})
    public Object methodOne() {
        if(this.grailsCacheManager != null) {
            LinkedHashMap $$__map = new LinkedHashMap();
            Cache $_cache_cacheVariable = this.grailsCacheManager.getCache("demo");
            Object $_cache_cacheKey = this.customCacheKeyGenerator.generate("com.demo.DemoService", "methodOne", this.hashCode(), $$__map, (String)null);
            ValueWrapper $_cache_valueWrapper = $_cache_cacheVariable.get($_cache_cacheKey);
            if($_cache_valueWrapper != null) {
                return $_cache_valueWrapper.get();
            } else {
                Object $_cache_originalMethodReturnValue = this.$$_cache_methodOne();
                $_cache_cacheVariable.put($_cache_cacheKey, $_cache_originalMethodReturnValue);
                return $_cache_originalMethodReturnValue;
            }
        } else {
            return this.$$_cache_methodOne();
        }
    }

    @Cacheable(
        key = "#argTwo",
        value = {"demo"}
    )
    public Object methodTwo(String argOne, String argTwo) {
        if(this.grailsCacheManager != null) {
            LinkedHashMap $$__map = new LinkedHashMap();
            $$__map.put("argOne", argOne);
            $$__map.put("argTwo", argTwo);
            Cache $_cache_cacheVariable = this.grailsCacheManager.getCache("demo");
            Object $_cache_cacheKey = this.customCacheKeyGenerator.generate("com.demo.DemoService", "methodTwo", this.hashCode(), $$__map, (String)"#argTwo");
            ValueWrapper $_cache_valueWrapper = $_cache_cacheVariable.get($_cache_cacheKey);
            if($_cache_valueWrapper != null) {
                return $_cache_valueWrapper.get();
            } else {
                Object $_cache_originalMethodReturnValue = this.$$_cache_methodTwo(argOne, argTwo);
                $_cache_cacheVariable.put($_cache_cacheKey, $_cache_originalMethodReturnValue);
                return $_cache_originalMethodReturnValue;
            }
        } else {
            return this.$$_cache_methodTwo(argOne, argTwo);
        }
    }

    @Cacheable(
        condition = "#x < 10",
        value = {"basic"}
    )
    public Object multiply(int x, int y) {
        if(this.grailsCacheManager != null) {
            LinkedHashMap $$__map = new LinkedHashMap();
            $$__map.put("x", Integer.valueOf(x));
            $$__map.put("y", Integer.valueOf(y));
            Cache $_cache_cacheVariable = this.grailsCacheManager.getCache("basic");
            if(DefaultTypeTransformation.booleanUnbox(ScriptBytecodeAdapter.invokeStaticMethodN(DemoService.class, CacheConditionUtils.class, "shouldCache", new Object[]{this, $$__map, "#x < 10"}))) {
                Object $_cache_cacheKey = this.customCacheKeyGenerator.generate("com.demo.DemoService", "multiply", this.hashCode(), $$__map, (String)null);
                ValueWrapper $_cache_valueWrapper = $_cache_cacheVariable.get($_cache_cacheKey);
                if($_cache_valueWrapper != null) {
                    return $_cache_valueWrapper.get();
                } else {
                    Object $_cache_originalMethodReturnValue = this.$$_cache_multiply(x, y);
                    $_cache_cacheVariable.put($_cache_cacheKey, $_cache_originalMethodReturnValue);
                    return $_cache_originalMethodReturnValue;
                }
            } else {
                return this.$$_cache_multiply(x, y);
            }
        } else {
            return this.$$_cache_multiply(x, y);
        }
    }

    protected Object $$_cache_methodOne() {
        return Integer.valueOf(42);
    }

    protected Object $$_cache_methodTwo(String argOne, String argTwo) {
        return Integer.valueOf(2112);
    }

    protected Object $$_cache_multiply(int x, int y) {
        return Integer.valueOf(x * y);
    }

    public GrailsCacheKeyGenerator getCustomCacheKeyGenerator() {
        return this.customCacheKeyGenerator;
    }

    public void setCustomCacheKeyGenerator(GrailsCacheKeyGenerator var1) {
        this.customCacheKeyGenerator = var1;
    }

    public CacheManager getGrailsCacheManager() {
        return this.grailsCacheManager;
    }

    public void setGrailsCacheManager(CacheManager var1) {
        this.grailsCacheManager = var1;
    }
}
Clone this wiki locally