首先,爲何會碰到這樣的問題?java
昨天寫的一個業務上線了,可是在dev環境和test環境都能跑,可是到了線上環境發生數據不能插入的問題。
問了老大以後發現線上數據庫是讀寫分離的,而後經過過濾器的才能進入寫數據庫卡,個人函數命名規範問題不符合過濾器的要求,致使從controller不能進入邏輯函數。面試
主要緣由:spring
AOP目標是把業務的共性問題提取出來集中放到一個統一的地方管理和控制。sql
不一樣方法在java的完整週期(類加載期間,編譯期,運行期間等)中不一樣的時間段插入切面的方式不一樣(即咱們想要他在這個時間完成的方法,這裏建議先了解AOP的5種加強類型)。數據庫
Cglib 是一個強大的,高性能的 Code 生成類庫。
原理是在運行期間目標字節碼加載後,經過字節碼技術爲一個類建立子類,
並在子類中採用方法攔截的技術攔截全部父類方法的調用,順勢織入橫切邏輯。
因爲是經過子類來代理父類,所以不能代理被 final 字段修飾的方法。
複製代碼
在java編譯期間有不一樣的織入方法 編程
自動代理 基於註解的方式 或 xml方式 本項目是使用Spring+AspectJ:基於xml:aop:config的方式實現AOP織入。緩存
基於代理(jdk動態代理、cglib動態代理)實現的aop Spring aop使用了兩種代理機制。一種是jdk動態代理,另外一種是cglib動態代理。 Jdk動態代理只支持接口代理,cglib支持類的代理。
下面這張退很好的總結了AOP的知識點。本人可能總結的不對,有問題請評論提醒。 安全
1.將讀操做和寫操做分離到不一樣的數據庫上,避免主服務器出現性能瓶頸;
2.主服務器進行寫操做時,不影響查詢應用服務器的查詢性能,下降阻塞,提升併發;
3.數據擁有多個容災副本,提升數據安全性。
4.同時當主服務器故障時,可當即切換到其餘服務器,提升系統可用性;
複製代碼
一、冷備份(定時全量/增量備份)
二、熱備份(在主從架構上實現)
三、主從架構(N主M從)
四、讀寫分離(在主從架構上實現)
五、數據分片(分庫分表(垂直分庫 水平分表))
複製代碼
參考:www.jianshu.com/p/b7834c990…springboot
一、Master將數據改變記錄到二進制日誌(binary log)中,也就是配置文件log-bin指定的文件,這些記錄叫作二進制日誌事件(binary log events)
二、Slave經過I/O線程讀取Master中的binary log events並寫入到它的中繼日誌(relay log)
三、Slave重作中繼日誌中的事件,把中繼日誌中的事件信息一條一條的在本地執行一次,完成數據在本地的存儲,從而實現將改變反映到它本身的數據(數據重放)
複製代碼
data數據源列表:master 寫庫 slave 讀庫
數據源DynamicDataSource類須要經過繼承AbstractRoutingDataSource,class位於com.A.B.DynamicDataSource
<bean id="dynamicDataSource" class="com.A.B.DynamicDataSource">
<property name="targetDataSources">
<map key-type="java.lang.String">
<entry key="master" value-ref="masterDataSource" />
<entry key="slave" value-ref="slaveDataSource" />
</map>
</property>
<property name="defaultTargetDataSource" ref="masterDataSource" />
</bean>
配置dataAOP 動態設置數據源,class位於com.T.A.dsadvice.DataSourceAdvice
<bean id="dataSourceAdvice" class="com.T.A.dsadvice.DataSourceAdvice" />
配置事務
<!-- spring aop manager transaction -->
<tx:advice id="txTransactionAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- add transaction -->
<tx:method name="add*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="create*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="save*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="insert*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="update*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="change*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="modify*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="edit*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="delete*" propagation="REQUIRED" rollback-for="Exception"/>
<tx:method name="remove*" propagation="REQUIRED" rollback-for="Exception"/>
</tx:attributes>
</tx:advice>
經過配置aop:config實現AOP:AspectJ
<aop:config>
<aop:advisor advice-ref="dataSourceAdvice" pointcut="execution(* com.T.A.service..*Service.*(..))" order="1"/>
<aop:advisor advice-ref="txTransactionAdvice" pointcut="execution(* com.T.A.service..*Service.*(..)))" order="2" />
</aop:config>
複製代碼
//determineCurrentLookupKey是重寫的AbstractRoutingDataSource的方法
//主要是肯定當前應該使用哪一個數據源的key,由於AbstractRoutingDataSource 中保存的多個數據源是經過Map的方式保存的
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceSwitcher.getDataSource();
}
}
複製代碼
public class DataSourceAdvice implements MethodBeforeAdvice, AfterReturningAdvice, ThrowsAdvice
複製代碼
一共三個數據源:master slave 動態數據源 保存在master和slave,爲了防止spring注入異常,因此master和slave都是主動實例化的,並非交給spring管理bash
MybatisConfiguration 主要是配置的sqlSessionFactory和sqlSessionTemplate,以及Mybatis的擴展框架Mapper的配置,若是不須要Mapper,能夠不用配置scannerConfigurer
@Before是在方法執行前執行
@After在方法執行後執行
@Around環繞執行,能夠再方法執行先後操做
@Aspect放在類名上面,把當前類標識爲一個切面供容器讀取
@Pointcut切入點,此註解放在方法上面,指向須要使用的切面編程的方法。此註解下面的方法並不會執行
複製代碼
總結本項目中使用AOP實現主從分離的方式:
對於AOP來講,最重要的點在於: