二、Mybatis結合外掛實現讀寫分離(動態切換資料來源)、Aop切面使用註解實現動態資料來源配置
阿新 • • 發佈:2022-03-15
(一)使用Mybatis外掛
在繼承之上修改,使用Mybatis外掛(上一篇文章基礎上修改:一、springboot druid連線池實現多資料來源動態切換方式(繼承介面:AbstractRoutingDataSource) - 程式碼紅了一大片 - 部落格園 (cnblogs.com))
新增一個對應的攔截器配置
@Intercepts( {@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}), @Signature(type= Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})})
//在Mybatis中對操作的分類分為兩種(update:增刪改)(query:查) public class DynamicDataSourcePlugin implements Interceptor { @Override public Object intercept(Invocation invocation) throwsThrowable { // 拿到當前方法(update、query)所有引數 Object[] objects = invocation.getArgs(); // MappedStatement 封裝CRUD所有的元素和SQL MappedStatement ms = (MappedStatement) objects[0]; // 讀方法 if (ms.getSqlCommandType().equals(SqlCommandType.SELECT)) { //在這裡可以設定使用的資料來源物件,這裡的資料來源物件是上一個加成類相同的資料來源配置 DynamicDataSource.name.set("R1"); } else { // 寫方法 DynamicDataSource.name.set("R3"); } // 修改當前執行緒要選擇的資料來源的key return invocation.proceed(); } @Override public Object plugin(Object target) { if (target instanceof Executor) { return Plugin.wrap(target, this); } else { return target; } } @Override public void setProperties(Properties properties) { } }
將對應的配置在配置類中使用@Bean注入到容器中
@Bean public Interceptor dynamicDataSourcePlugin(){ return new DynamicDataSourcePlugin(); }
(二)Aop切面註解實現(適用於不同的資料來源)
注意:適用下面自動配置切面代理在主類上
@EnableAspectJAutoProxy(exposeProxy=true)
實現一個自定義註解:
//目標物件,可以是方法,可以是類,也可以設定為欄位屬性
@Target({ElementType.METHOD,ElementType.TYPE}) //保留級別: //SOURCE:註釋將被編譯器丟棄 //RUNTIME:註釋將由編譯器記錄在類檔案中,並在執行時由 VM 保留,因此可以反射性地讀取它們 //CLASS:註釋將由編譯器記錄在類檔案中,但不需要在執行時由 VM 保留。這是預設行為。 @Retention(RetentionPolicy.RUNTIME) public @interface TargetDataSource { String value() default "R1"; }
實現一個切面:(確保在被註解修飾的類上可以被掃描到)
@Component
@Aspect
public class DynamicDataSourceAspect {
//within(com.zjl.datasources.controller.*)表示在專案中,controller下的所有包使用都會被掃描到,也可以不使用
//@annotation(ts)表示是註解的切面
//(JoinPoint point,TargetDataSource ts)表示切入點和掃描到的註解類(ts.value()註解中的value物件)
@Before("within(com.zjl.datasources.controller.*) && @annotation(ts)")
public void before(JoinPoint point, TargetDataSource ts){
String value = ts.value();
DynamicDataSource.name.set(value);
System.out.println(value);
}
}