SPringBoot使用方法注解拦截器时遇到不生效问题记录:
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface DataScope
{
boolean enable() default true;
}
@Getter
@EqualsAndHashCode(callSuper = true)
@Component
public class DataPermissionAnnotationAdvisor extends AbstractPointcutAdvisor {
private final Advice advice;
private final Pointcut pointcut;
public DataPermissionAnnotationAdvisor() {
this.advice = new DataScopeAnnotationInterceptor();
this.pointcut = this.buildPointcut();
}
protected Pointcut buildPointcut() {
Pointcut classPointcut = new AnnotationMatchingPointcut(DataScope.class, true);
Pointcut methodPointcut = new AnnotationMatchingPointcut(null, DataScope.class, true);
return new ComposablePointcut(classPointcut).union(methodPointcut);
}
}
public class DataScopeAnnotationInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
Logger log = LoggerFactory.getLogger(DataScopeAnnotationInterceptor.class);
log.debug("DataScopeAnnotationInterceptor 拦截器:" + methodInvocation.getMethod().getName());
try {
// 执行逻辑
return methodInvocation.proceed();
} finally {
// 出栈
if (dataPermission != null) {
DataPermissionContextHolder.remove();
}
}
}
}
@Service
public class UserService {
@DataScope
public void method01() {
// 查询订单
UserDO user = userMapper.selectById(1);
System.out.println(user);
}
}
完成以上全部代码,在调用motho01()方法时,正常就应该先执行拦截器,再执行method01中的方法。但在springboot-2.1.3RELEASE版本时,拦截器却没有生效。
网上搜罗一圈没有现成的办法,只能老老实实看源码了,功夫不负有心人,请看以下源码:
public class InfrastructureAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator {
@Nullable
private ConfigurableListableBeanFactory beanFactory;
public InfrastructureAdvisorAutoProxyCreator() {
}
protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
super.initBeanFactory(beanFactory);
this.beanFactory = beanFactory;
}
//在获取拦截器时,通过这个方法判断是否是有效拦截器的意思。
//其中 this.beanFactory.getBeanDefinition(beanName).getRole() == 2 这个条件就是导致拦截器不生效的小虫子。
protected boolean isEligibleAdvisorBean(String beanName) {
return this.beanFactory != null && this.beanFactory.containsBeanDefinition(beanName) && this.beanFactory.getBeanDefinition(beanName).getRole() == 2;
}
}
解决办法:
像这样就可以了。
@Getter
@EqualsAndHashCode(callSuper = true)
@Component
@Role(2)
public class DataPermissionAnnotationAdvisor extends AbstractPointcutAdvisor {
private final Advice advice;
private final Pointcut pointcut;
public DataPermissionAnnotationAdvisor() {
this.advice = new DataScopeAnnotationInterceptor();
this.pointcut = this.buildPointcut();
}
protected Pointcut buildPointcut() {
Pointcut classPointcut = new AnnotationMatchingPointcut(DataScope.class, true);
Pointcut methodPointcut = new AnnotationMatchingPointcut(null, DataScope.class, true);
return new ComposablePointcut(classPointcut).union(methodPointcut);
}
}
通常用户定义的bean,role的值都是0,而springboot内核bean的role值才为2。所以我看到有自动配置插件中没有手动添加Role注解,依然能拦截,我想就是这个原因吧。
其他的办法,欢迎留言补充。