springboot 拦截器之Advisor不生效问题
2023-12-14 16:43:54
SPringBoot使用方法注解拦截器时遇到不生效问题记录:
- 定义方法注解
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface DataScope
{
boolean enable() default true;
}
- 定义 Advisor
@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;
}
}
解决办法:
- 只需在DataPermissionAnnotationAdvisor 类上方添加Role(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);
}
}
@Role注解
- 标识Bean的类别
- 种类:
-
- ROLE_APPLICATION = 0
- bean的默认角色
- 标识应用的主要的主要角色
- 通常对应于用户定义的bean
-
- ROLE_APPLICATION = 1
- 标识较大配置的一部分
- 通常是仔细观察特定的ComponentDefinition时重要的提示,而不是体现在应用中
-
- ROLE_INFRASTRUCTURE = 2
- 标识后台角色,与最终用户无关
- 通常供是内部工作的bean使用
通常用户定义的bean,role的值都是0,而springboot内核bean的role值才为2。所以我看到有自动配置插件中没有手动添加Role注解,依然能拦截,我想就是这个原因吧。
其他的办法,欢迎留言补充。
文章来源:https://blog.csdn.net/ldz_wolf/article/details/134993502
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!