In Spring AOP (AspectJ) können Punktschnitte, bei denen die an die Schnittstelle angehängte Anmerkung als Markierung verwendet wird, nicht verwendet werden. Daher ist es nicht möglich, einen Interceptor als Anmerkungszeichen in die Methode der Mapper-Schnittstelle von MyBatis einzufügen.
Die an die Methode angehängte Anmerkung wird nicht von der Methode der geerbten Klasse (oder der Klasse, die die Schnittstelle implementiert) geerbt. Und da Spring AOP (oder AspectJ) auf instanziierte Beans abzielt, deren Typ die Klasse ist, die die Schnittstelle implementiert, werden die an die Methoden der Schnittstelle angehängten Anmerkungen nicht überprüft.
Die an die Benutzeroberfläche angehängte Anmerkung wird auch verwendet, indem "AspectJPointcutAdvisor" so angepasst wird, dass sie zum Zeitpunkt der Pointcut-Beurteilung überprüft wird.
Da es eine Methode gibt, um den Punktschnitt zu erhalten, überschreiben Sie diese und überprüfen Sie auch die Schnittstellenanmerkungen.
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));
}
}
}
Registrieren Sie den Advisor mit dem "InterfaceMethodAwareAspectJPointcutAdvisor", der auch die oben erstellten Schnittstellenanmerkungen überprüft.
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