资讯专栏INFORMATION COLUMN

Spring Boot中自定义注解+AOP实现主备库切换

zhisheng / 675人阅读

摘要:示例代码如下添加的设置默认的配置对应的是原来的如何使用注解从主库到备库的切换

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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/75740.html

相关文章

  • Spring Boot [配置-下篇]

    摘要:进行异常的捕捉与错误信息页面的定制。告诉,这是一个对象,该对象应该被注册为在应用程序上下文中的。不同框架的不同配置这里以作为演示默认情况下,保护已启用。你必须配置包含令牌的所有的网页来工作。该命名结构旨在帮你找到需要的。 导读: 在上篇文章中我们了解到Spring Boot 的一些常用的外部化配置,在本篇中我们将会继续对类的配置进行了解 一个简单的例子[错误页面定制]: 在 Spr...

    StonePanda 评论0 收藏0
  • Javag工程师成神之路(2019正式版)

    摘要:结构型模式适配器模式桥接模式装饰模式组合模式外观模式享元模式代理模式。行为型模式模版方法模式命令模式迭代器模式观察者模式中介者模式备忘录模式解释器模式模式状态模式策略模式职责链模式责任链模式访问者模式。 主要版本 更新时间 备注 v1.0 2015-08-01 首次发布 v1.1 2018-03-12 增加新技术知识、完善知识体系 v2.0 2019-02-19 结构...

    Olivia 评论0 收藏0
  • Spring Boot Aop

    摘要:面向切面的程序设计思想也是面向切面软件开发的基础。与切面相关的编程概念还包括元对象协议主题混入和委托。切面声明类似于中的类声明,在中会包含着一些以及相应的。 spring-boot-aop 什么是aop 面向切面的程序设计(Aspect-oriented programming,AOP,又译作面向方面的程序设计、剖面导向程序设计)是计算机科学中的一种程序设计思想,旨在将横切关注点与业务...

    Channe 评论0 收藏0
  • 猫头鹰的深夜翻译:使用SpringBoot和AspectJ实现AOP

    摘要:我们会写切面来拦截对这些业务类和类的调用。切面定义何时拦截一个方法以及做什么和在一起成为切面连接点当代码开始执行,并且切点的条件满足时,通知被调用。 前言 这篇文章会帮助你使用Spring Boot Starter AOP实现AOP。我们会使用AspectJ实现四个不同的通知(advice),并且新建一个自定义的注解来追踪方法的执行时间。 你将会了解 什么是交叉分割关注点(cross...

    meislzhua 评论0 收藏0
  • SpringBoot基础篇AOP之基本使用姿势小结

    摘要:通知和切点共同定义了关于切面的全部内容,它是什么时候,在何时和何处完成功能引入允许我们向现有的类添加新的方法或者属性组装方面来创建一个被通知对象。这可以在编译时完成例如使用编译器,也可以在运行时完成。和其他纯框架一样,在运行时完成织入。 原文:190301-SpringBoot基础篇AOP之基本使用姿势小结 一般来讲,谈到Spring的特性,绕不过去的就是DI(依赖注入)和AOP(切...

    timger 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<