Spring Boot中自定义注解结合AOP实现主备库切换问题

这篇文章主要介绍了Spring Boot中自定义注解+AOP实现主备库切换的相关知识,本篇文章的场景是做调度中心和监控中心时的需求,后端使用TDDL实现分表分库,需要的朋友可以参考下

摘要:本篇文章的场景是做调度中心和监控中心时的需求,后端使用TDDL实现分表分库,需求:实现关键业务的查询监控,当用Mybatis查询数据时需要从主库切换到备库或者直接连到备库上查询,从而减小主库的压力,在本篇文章中主要记录在Spring Boot中通过自定义注解结合AOP实现直接连接备库查询

一.通过AOP 自定义注解实现主库到备库的切换

1.1 自定义注解

自定义注解如下代码所示

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.METHOD) public @interface SwitchDataBase { boolean switch2Backup() default false; }

1.2 实现方法拦截器对自定义注解处理

import java.lang.reflect.Method; import java.util.Arrays; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; /** * 处理走备库逻辑的注解 */ @Component public class SwitchDataBaseInterceptor implements MethodInterceptor { private final Logger log = LoggerFactory.getLogger(SwitchDataBaseInterceptor.class); @Override public Object invoke(MethodInvocation invocation) throws Throwable { Method method = invocation.getmethod(); SwitchDataBase annotation = getAnnotation(method); if (annotation == null) { return invocation.proceed(); } Object val = null; if(!ThreadLocalmap.containsKey(GroupDataSourceRouteHelper.DATASOURCE_INDEX)) { if (annotation.switch2Backup()) { log.info("query back up DB, method: " + method.getName()); GroupDataSourceRouteHelper.executeByGroupDataSourceIndex(1, true); } else { log.info("query primary DB, method: " + method.getName()); GroupDataSourceRouteHelper.executeByGroupDataSourceIndex(0, true); } } try { val = invocation.proceed(); } catch (Exception e) { log.info(method.getDeclaringClass().getName() + "." + invocation.getmethod().getName() + "方法调用失败,arguments:" + Arrays.toString(invocation.getArguments())); throw new RuntimeException(e); } finally { GroupDataSourceRouteHelper.removeGroupDataSourceIndex(); } return val; } /** * 找方法上面声明的注解 */ private SwitchDataBase getAnnotation(Method method) { if (method.isAnnotationPresent(SwitchDataBase.class)) { return method.getAnnotation(SwitchDataBase.class); } return null; } }

1.3 配置OverallQueryConfiguration

在Spring Boot中装配AOP Bean,实现扫描特定目录下的注解,实现切面变成形成通知处理。示例代码如下

import com.wdk.wms.annotation.SwitchDataBaseInterceptor; import org.springframework.aop.Advisor; import org.springframework.aop.support.DefaultpointcutAdvisor; import org.springframework.aop.support.JdkRegexpMethodpointcut; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class SwitchDataBaseConfiguration { @Bean(name = "overallQueryInterceptor") public SwitchDataBaseInterceptor overallQueryInterceptor() { return new SwitchDataBaseInterceptor(); } //添加aop的pointcut @Bean(name = "jdkRegexpMethodpointcut") public JdkRegexpMethodpointcut jdkRegexpMethodpointcut() { JdkRegexpMethodpointcut jdkRegexpMethodpointcut = new JdkRegexpMethodpointcut(); jdkRegexpMethodpointcut.setPatterns("com.wdk.wms.mapper.*"); return jdkRegexpMethodpointcut; } //设置认的aop配置对应的是原来的 @Bean public Advisor druidAdvisor() { DefaultpointcutAdvisor defaultpointcutAdvisor = new DefaultpointcutAdvisor(); defaultpointcutAdvisor.setpointcut(jdkRegexpMethodpointcut()); defaultpointcutAdvisor.setAdvice(overallQueryInterceptor()); return defaultpointcutAdvisor; } }

1.4 如何使用注解从主库到备库的切换

@SwitchDataBase(switch2Backup = true) List listByTemplateOver3(@Param("templates") List templates);

总结

如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

相关文章

HashMap是Java中最常用的集合类框架,也是Java语言中非常典型...
在EffectiveJava中的第 36条中建议 用 EnumSet 替代位字段,...
介绍 注解是JDK1.5版本开始引入的一个特性,用于对代码进行说...
介绍 LinkedList同时实现了List接口和Deque接口,也就是说它...
介绍 TreeSet和TreeMap在Java里有着相同的实现,前者仅仅是对...
HashMap为什么线程不安全 put的不安全 由于多线程对HashMap进...