Spring AOP 拦截注解接口的所有方法
背景
MyBatis 多源数据库切换问题,希望通过注解标注 Dao 类的数据库源,但使用注解切点表达式,因实现类是 MyBatis 动态代理生成,无法在实现类上添加注解,而添加到接口上又无效,需要寻找替代方案。
解决方案
不采用 AspectJ 表达式方式定义切点和切面,使用 AnnotationMatchingPointcut 和 DefaultPointcutAdvisor 来定义。
实现方式
示例代码如下,将 ChangeMySqlType 注解添加到接口上,即可拦截实现类的方法。
类注解
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ChangeMySqlType {
}
Aspect 实现
import lombok.extern.slf4j.Slf4j;
import org.aopalliance.aop.Advice;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.aop.Advisor;
import org.springframework.aop.Pointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.support.annotation.AnnotationMatchingPointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
@Slf4j
@Aspect
@Component
@Order(2)
public class ChangeMySqlTypeAspect {
@Autowired
DataBasesConfig dataBasesConfig;
@Bean
public Advisor dataSourceAdvisor(){
Pointcut pointcut = new AnnotationMatchingPointcut(ChangeMySqlType.class, true);
Advice advice = new MethodAroundAdvice(dataBasesConfig);
return new DefaultPointcutAdvisor(pointcut, advice);
}
}
Advice 实现
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
@Slf4j
@Component
public class MethodAroundAdvice implements MethodBeforeAdvice, AfterReturningAdvice {
private DataBasesConfig dataBasesConfig;
public MethodAroundAdvice(DataBasesConfig dataBasesConfig){
this.dataBasesConfig = dataBasesConfig;
}
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
log.info("before {} called", method.getName());
}
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
log.info("after {} called", method.getName());
}
}
相关文章