[JAVA] Correspond aux annotations sur l'interface avec Spring AOP


problème

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.

Cause

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.

Solution

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.

Extension d'AspectJPointcutAdvisor

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));
        }
    }
}

Classe de configuration

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

Correspond aux annotations sur l'interface avec Spring AOP
gRPC sur Spring Boot avec grpc-spring-boot-starter
Programmation avec ruby (en route)
Spring AOP pour la première fois
Utilisez des modèles sur le chemin de classe avec Apache Velocity
Sortez avec un suffixe sur la méthode
Publiez l'application avec ruby on rails
Sortez avec un suffixe sur la méthode 2
Déterminez la page actuelle avec Ruby on Rails
À propos de Spring AOP
À propos de Spring AOP
Tirez parti de la barrière cyclique Spring AOP + pour garantir des conditions de test de verrouillage optimistes sur l'application Spring Boot
Refactoriser l'implémentation du pattern Decorator avec une interface fonctionnelle
Ressort avec Kotorin ―― 3. Omettre les crochets d'onde de la fonction
Accédez au h2db intégré de Spring Boot avec jdbcTemplate
Afficher la liste en setDétails à l'écran avec ressort-sécurité
Une note de révision de l'interface Spring Framework Resource
Déployer le projet Spring Boot sur Tomcat dans XAMPP
Contrôlez le flux de traitement Spring Batch avec JavaConfig.