@CacheResult
public String getValue() {
return cpuIntensiveCalculation();
}
@CacheResult
public List<String> getOtherValue(int one, int two) {
return cpuIntensiveCalculation(one, two);
}
@CacheResult
public ComplexObject getOtherValue(ComplexObject foo) {
return cpuIntensiveCalculation(foo);
}
Doesn't really seem I can use MethodDelegation…since I don't know what class/method until its annotated. Do I maybe need to generate byte code that extends the annotation interface instead? For example, if I have:
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface CacheResult {
String cacheName()
}
class CacheResultImpl implements CacheResult {
private String name;
@Override
public Class<? extends Annotation> annotationType() {
return Cacheable.class;
}
@Override
public String name() {
return name;
}
}
Do I write the *interceptor* logic as part of CacheResultImpl? If so, then how do I invoke the annotated method…as well as access the method name, and arguments?
thanks in advance,
cOrE_dUmPeR
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface CacheResult {
String cacheName()
}
public class CacheResultInterceptor
@RuntimeType
public static Object intercept(@DefaultCall final Callable<?> zuper, @Origin final Method method, @AllArguments final Object…args) {
CacheKey key = KeyGenerator.generate(args); // static method call to KeyGenerator
String cacheName = method.getAnnotation(CacheResult.class).cacheName(); // annotation has cache name
Cache cache = CacheManager.getCache(cacheName); // static method call to CacheManager
Object value = cache.get(key);
if(cachedValue == null) {
value = zuper.call()
cache.put(key, result);
}
LOGGER.debug("returning value " + value.toString() + " from intercepted method " + method.getName());
return value;
}
Class<? extends Object> dynamicType = new ByteBuddy()
.subclass(Object.class)
.method(isAnnotatedBy(CacheResult.class))
.intercept(MethodDelegation.to(CacheResultInterceptor.class))
.make()
.load(this.getClass().getClassLoader(), ClassLoadingStrategy.Default.INJECTION).getLoaded();
@CachResult(name = "user_cache")
public User getById(final String id) {
return userDao.find(id);
}
}
.method(isAnnotatedBy(CacheResult.class))
.intercept(MethodDelegation.to(CacheResultInterceptor.class))
.make()
.load(this.getClass().getClassLoader(), ClassLoadingStrategy.Default.INJECTION)
.getLoaded()
.newInstance()
.getById("foo"); // is intercepted