Created
December 16, 2016 10:45
-
-
Save roberthunt/78392cbca46eeb33c803ce0294f1e847 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import org.aspectj.lang.JoinPoint; | |
import org.aspectj.lang.annotation.Aspect; | |
import org.aspectj.lang.annotation.Before; | |
import org.aspectj.lang.reflect.MethodSignature; | |
import org.slf4j.Logger; | |
import org.slf4j.LoggerFactory; | |
import java.lang.annotation.Annotation; | |
import java.lang.reflect.Executable; | |
import java.lang.reflect.Field; | |
import java.lang.reflect.InvocationTargetException; | |
import java.lang.reflect.Method; | |
import java.util.Map; | |
/** | |
* An Aspect which removes a specific annotation from a Spring Data JPA repository method. This was designed to remove | |
* the org.springframework.data.jpa.repository.QueryHints annotation when running tests with database drivers which | |
* don't support specific query hints (and throw exceptions causing the tests to fail). | |
* | |
* Note: make sure that AspectJ auto-proxy is enabled either via the @EnableAspectJAutoProxy annotation in the Java | |
* configuration or <aop:aspectj-autoproxy /> in the XML configuration. | |
* | |
* @author Robert Hunt | |
*/ | |
@Aspect | |
public class JpaRepositoryAnnotationRemovingAspect | |
{ | |
private static final Logger LOG = LoggerFactory.getLogger(JpaRepositoryAnnotationRemovingAspect.class); | |
private final Class<? extends Annotation> targetAnnotation; | |
public JpaRepositoryAnnotationRemovingAspect(Class<? extends Annotation> targetAnnotation) | |
{ | |
this.targetAnnotation = targetAnnotation; | |
} | |
@Before("execution(public * org.springframework.data.jpa.repository.JpaRepository+.*(..))") | |
public void interceptRepositoryMethod(JoinPoint joinPoint) | |
{ | |
Method method = ((MethodSignature) joinPoint.getSignature()).getMethod(); | |
try | |
{ | |
// the "declaredAnnotations" field is lazily initialised so we need to call the method first which will initialise it | |
Method declaredAnnotationsMethod = Executable.class.getDeclaredMethod("declaredAnnotations"); | |
declaredAnnotationsMethod.setAccessible(true); | |
declaredAnnotationsMethod.invoke(method); | |
// the "declaredAnnotations" field contains all of the method annotations | |
Field declaredAnnotationsField = Executable.class.getDeclaredField("declaredAnnotations"); | |
declaredAnnotationsField.setAccessible(true); | |
Map<Class<? extends Annotation>, Annotation> declaredAnnotations = (Map<Class<? extends Annotation>, Annotation>) declaredAnnotationsField.get(method); | |
if (declaredAnnotations != null && declaredAnnotations.containsKey(targetAnnotation)) | |
{ | |
LOG.info("[{}] annotation was found on method [{}] and will be removed", targetAnnotation, method); | |
declaredAnnotations.remove(targetAnnotation); | |
} | |
} | |
catch (NoSuchMethodException | InvocationTargetException | NoSuchFieldException | IllegalAccessException e) | |
{ | |
LOG.error("unable to access declaredAnnotations method and/or field on method [{}]", method); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment