Spring Boot中自定義注解結(jié)合AOP實(shí)現(xiàn)主備庫(kù)切換問(wèn)題
摘要:本篇文章的場(chǎng)景是做調(diào)度中心和監(jiān)控中心時(shí)的需求,后端使用TDDL實(shí)現(xiàn)分表分庫(kù),需求:實(shí)現(xiàn)關(guān)鍵業(yè)務(wù)的查詢監(jiān)控,當(dāng)用Mybatis查詢數(shù)據(jù)時(shí)需要從主庫(kù)切換到備庫(kù)或者直接連到備庫(kù)上查詢,從而減小主庫(kù)的壓力,在本篇文章中主要記錄在Spring Boot中通過(guò)自定義注解結(jié)合AOP實(shí)現(xiàn)直接連接備庫(kù)查詢。
一.通過(guò)AOP 自定義注解實(shí)現(xiàn)主庫(kù)到備庫(kù)的切換
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 實(shí)現(xiàn)方法攔截器對(duì)自定義注解處理
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; /** * 處理走備庫(kù)邏輯的注解 */ @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() + "方法調(diào)用失敗,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,實(shí)現(xiàn)掃描特定目錄下的注解,實(shí)現(xiàn)切面變成形成通知處理。示例代碼如下
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; } //設(shè)置默認(rèn)的aop配置對(duì)應(yīng)的是原來(lái)的<aop:advisor> @Bean public Advisor druidAdvisor() { DefaultPointcutAdvisor defaultPointcutAdvisor = new DefaultPointcutAdvisor(); defaultPointcutAdvisor.setPointcut(jdkRegexpMethodPointcut()); defaultPointcutAdvisor.setAdvice(overallQueryInterceptor()); return defaultPointcutAdvisor; } }
1.4 如何使用注解從主庫(kù)到備庫(kù)的切換
@SwitchDataBase(switch2Backup = true) List<ConsumerNoticeMsg> listByTemplateOver3(@Param("templates") List<Integer> templates);
總結(jié)
以上所述是小編給大家介紹的Spring Boot中自定義注解結(jié)合AOP實(shí)現(xiàn)主備庫(kù)切換,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
如果你覺(jué)得本文對(duì)你有幫助,歡迎轉(zhuǎn)載,煩請(qǐng)注明出處,謝謝!
相關(guān)文章
springboot集成schedule實(shí)現(xiàn)定時(shí)任務(wù)
在項(xiàng)目開(kāi)發(fā)過(guò)程中,我們經(jīng)常需要執(zhí)行具有周期性的任務(wù)。通過(guò)定時(shí)任務(wù)可以很好的幫助我們實(shí)現(xiàn)。本篇文章主要介紹了springboot集成schedule實(shí)現(xiàn)定時(shí)任務(wù),感興趣的小伙伴們可以參考一下2018-05-05IDEA項(xiàng)目中配置Maven鏡像源(下載源)的詳細(xì)過(guò)程
Maven是一個(gè)能使我們的java程序開(kāi)發(fā)節(jié)省時(shí)間和精力,是開(kāi)發(fā)變得相對(duì)簡(jiǎn)單,還能使開(kāi)發(fā)規(guī)范化的工具,下面這篇文章主要給大家介紹了關(guān)于IDEA項(xiàng)目中配置Maven鏡像源(下載源)的詳細(xì)過(guò)程,需要的朋友可以參考下2024-02-02基于Java SSM框架實(shí)現(xiàn)簡(jiǎn)易的評(píng)教系統(tǒng)
這篇文章主要介紹了通過(guò)Java SSM框架實(shí)現(xiàn)一個(gè)簡(jiǎn)易的評(píng)教系統(tǒng)的示例代碼,文中的代碼講解詳細(xì),感興趣的小伙伴可以了解一下2022-02-02springboot2.0?@Slf4j?log?彩色日志配置輸出到文件
這篇文章主要介紹了springboot2.0 @Slf4j log日志配置輸出到文件(彩色日志),解決方式是使用了springboot原生自帶的一個(gè)log框架,結(jié)合實(shí)例代碼給大家講解的非常詳細(xì),需要的朋友可以參考下2023-08-08