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

网友投稿 460 2023-07-29

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

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

摘要:本篇文章的场景是做调度中心和监控中心时的需求,后端使用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.getNameICZikWX());

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

总结

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Restful API中的错误处理方法
下一篇:Intellij IDEA调试技巧的深入讲解
相关文章

 发表评论

暂时没有评论,来抢沙发吧~