Dans Spring AOP (AspectJ), les coupes ponctuelles utilisant l'annotation attachée à l'interface comme marque ne peuvent pas être utilisées. Par conséquent, il n'est pas possible d'insérer un intercepteur comme marque d'annotation dans la méthode de l'interface Mapper de MyBatis.
L'annotation attachée à la méthode n'est pas héritée par la méthode de la classe héritée (ou par la classe qui implémente l'interface). Et comme Spring AOP (ou AspectJ) cible les beans instanciés, dont le type est la classe qui implémente l'interface, les annotations attachées aux méthodes de l'interface ne sont pas inspectées.
L'annotation attachée à l'interface est également utilisée en personnalisant ʻAspectJPointcutAdvisor` de sorte qu'elle soit inspectée au moment du jugement de la coupe.
Puisqu'il existe une méthode pour obtenir le point de coupe, remplacez-la et vérifiez également les annotations d'interface.
InterfaceMethodAwareAspectJPointcutAdvisor.java
package aop;
import java.lang.reflect.Method;
import java.util.stream.Stream;
import org.springframework.aop.MethodMatcher;
import org.springframework.aop.Pointcut;
import org.springframework.aop.aspectj.AbstractAspectJAdvice;
import org.springframework.aop.aspectj.AspectJPointcutAdvisor;
import org.springframework.aop.support.ComposablePointcut;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.val;
public class InterfaceMethodAwareAspectJPointcutAdvisor extends AspectJPointcutAdvisor {
public InterfaceMethodAwareAspectJPointcutAdvisor(@NonNull AbstractAspectJAdvice advice) {
super(advice);
}
@Override
public Pointcut getPointcut() {
val original = super.getPointcut();
return new ComposablePointcut(original)
.union(new InterfaceAwareMethodMatcher(original.getMethodMatcher()));
}
@RequiredArgsConstructor
private static class InterfaceAwareMethodMatcher implements MethodMatcher {
@NonNull
private final MethodMatcher underlying;
@Override
public boolean isRuntime() {
return underlying.isRuntime();
}
@Override
public boolean matches(Method method, Class<?> targetClass) {
return Stream.of(targetClass.getInterfaces())
.anyMatch(x -> underlying.matches(method, x));
}
@Override
public boolean matches(Method method, Class<?> targetClass, Object... args) {
return Stream.of(targetClass.getInterfaces())
.anyMatch(x -> underlying.matches(method, x, args));
}
}
}
Enregistrez le conseiller en utilisant ʻInterfaceMethodAwareAspectJPointcutAdvisor` qui vérifie également les annotations d'interface créées ci-dessus.
AspectConfiguration.java
@Configuration
@EnableAspectJAutoProxy
public class AspectConfiguraiton implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(@NonNull ConfigurableListableBeanFactory factory) {
val original = new FooAspect();
val advisor = new ReflectiveAspectJAdvisorFactory()
.getAdvisors(new SingletonMetadataAwareAspectInstanceFactory(original, "fooAspect"));
advisors.stream()
.map(advisor -> new InterfaceMethodAwareAspectJPointcutAdivsor((AbstractAspectJAdvice) advisor))
.forEacth(advisor -> factory.registerSingleton(resolveName(advisor), advisor));
}
private static String resolveName(AspectJPointcutAdvisor advisor) {
val info = (AspectJPrecedenceInformation) advisor.getAdvice();
return info.getAspectName() + '#' + info.getDeclarationOrder();
}
}
Recommended Posts