package org.orienteer.core.dao.handler;

import java.lang.annotation.Annotation;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Method;
import java.util.Optional;

import org.joor.Reflect;
import org.orienteer.core.dao.IMethodHandler;

/**
 * {@link IMethodHandler} which invoke interfaces default method implementations
 * @param <T> type of target/delegate object
 */
public class DefaultInterfaceMethodHandler<T> implements IMethodHandler<T> {

	@Override
	public Optional<Object> handle(T target, Object proxy, Method method, Object[] args, InvocationChain<T> chain) throws Throwable {
		Class<?> declaringClass = method.getDeclaringClass();
		if(method.isDefault()) {
			MethodHandles.Lookup lookup = Reflect.onClass(MethodHandles.Lookup.class)
					.create(declaringClass, MethodHandles.Lookup.PRIVATE).get();
			return Optional.ofNullable(lookup.unreflectSpecial(method, declaringClass)
										  .bindTo(proxy)
										  .invokeWithArguments(args));
		} else if(proxy instanceof Annotation
						&& (args==null || args.length==0)
						&& !method.getDeclaringClass().equals(Annotation.class)) {
			Object defaultValue = method.getDefaultValue();
			if(defaultValue!=null) return Optional.of(defaultValue);
		}
		return chain.handle(target, proxy, method, args);
	}

}

package org.orienteer.core.dao.handler;

import java.lang.invoke.MethodHandles;
import java.lang.reflect.Method;
import java.util.Optional;

import org.joor.Reflect;
import org.orienteer.core.dao.IMethodHandler;

/**
 * {@link IMethodHandler} which invoke interfaces default method implementations
 * @param <T> type of target/delegate object
 */
public class DefaultInterfaceMethodHandler<T> implements IMethodHandler<T> {

	@Override
	public Optional<Object> handle(T target, Object proxy, Method method, Object[] args, InvocationChain<T> chain) throws Throwable {
		if(method.isDefault()) {
		Class<?> declaringClass = method.getDeclaringClass();
		MethodHandles.Lookup lookup = Reflect.onClass(MethodHandles.Lookup.class)
				.create(declaringClass, MethodHandles.Lookup.PRIVATE).get();
		return Optional.ofNullable(lookup.unreflectSpecial(method, declaringClass)
									  .bindTo(proxy)
									  .invokeWithArguments(args));
		} else return chain.handle(target, proxy, method, args);
	}

}

--- 
+++ 
@@ -1,5 +1,6 @@
 package org.orienteer.core.dao.handler;
 
+import java.lang.annotation.Annotation;
 import java.lang.invoke.MethodHandles;
 import java.lang.reflect.Method;
 import java.util.Optional;
@@ -15,14 +16,20 @@
 
 	@Override
 	public Optional<Object> handle(T target, Object proxy, Method method, Object[] args, InvocationChain<T> chain) throws Throwable {
+		Class<?> declaringClass = method.getDeclaringClass();
 		if(method.isDefault()) {
-		Class<?> declaringClass = method.getDeclaringClass();
-		MethodHandles.Lookup lookup = Reflect.onClass(MethodHandles.Lookup.class)
-				.create(declaringClass, MethodHandles.Lookup.PRIVATE).get();
-		return Optional.ofNullable(lookup.unreflectSpecial(method, declaringClass)
-									  .bindTo(proxy)
-									  .invokeWithArguments(args));
-		} else return chain.handle(target, proxy, method, args);
+			MethodHandles.Lookup lookup = Reflect.onClass(MethodHandles.Lookup.class)
+					.create(declaringClass, MethodHandles.Lookup.PRIVATE).get();
+			return Optional.ofNullable(lookup.unreflectSpecial(method, declaringClass)
+										  .bindTo(proxy)
+										  .invokeWithArguments(args));
+		} else if(proxy instanceof Annotation
+						&& (args==null || args.length==0)
+						&& !method.getDeclaringClass().equals(Annotation.class)) {
+			Object defaultValue = method.getDefaultValue();
+			if(defaultValue!=null) return Optional.of(defaultValue);
+		}
+		return chain.handle(target, proxy, method, args);
 	}
 
 }
Support of DAO'ing of Annotations
