一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務(wù)器之家 - 編程語言 - Java教程 - 詳解Spring AOP 實(shí)現(xiàn)主從讀寫分離

詳解Spring AOP 實(shí)現(xiàn)主從讀寫分離

2020-08-23 14:30Mafly Java教程

本篇文章主要介紹了Spring AOP 實(shí)現(xiàn)主從讀寫分離,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧

深刻討論為什么要讀寫分離?

為了服務(wù)器承載更多的用戶?提升了網(wǎng)站的響應(yīng)速度?分?jǐn)倲?shù)據(jù)庫服務(wù)器的壓力?就是為了雙機(jī)熱備又不想浪費(fèi)備份服務(wù)器?上面這些回答,我認(rèn)為都不是錯(cuò)誤的,但也都不是完全正確的。「讀寫分離」并不是多么神奇的東西,也帶不來多么大的性能提升,也許更多的作用的就是數(shù)據(jù)安全的備份吧。

從一個(gè)庫到讀寫分離,從理論上對(duì)服務(wù)器壓力來說是會(huì)帶來一倍的性能提升,但你仔細(xì)思考一下,你的應(yīng)用服務(wù)器真的很需要這一倍的提升么?那倒不如你去試著在服務(wù)器使用一下緩存系統(tǒng),如 Memcached、Redis 這些分布式緩存,那性能可能是幾十倍的提升。而且,在服務(wù)器硬件異常強(qiáng)悍及性能廉價(jià)的今天,完全更沒必要了,所以,在今天,我認(rèn)為它更多的職責(zé)就是為了數(shù)據(jù)安全而設(shè)計(jì)的,同時(shí)又提升了一些性能,這樣也挺好。

可能我們更應(yīng)該稱之為主從分離

利用 AOP 實(shí)現(xiàn)讀寫分離

讀寫分離方式很簡單,就是在你讀數(shù)據(jù)是去連接從庫,在你寫數(shù)據(jù)的時(shí)候去連接主庫,具體代碼實(shí)現(xiàn)當(dāng)然就是連接時(shí)候去操作了,這沒什么難度,在代碼里寫就是了。可是,有追求的程序猿都是不是這么解決問題的呢!

 其實(shí)通過上篇的 Spring AOP 攔截器的基本實(shí)現(xiàn) 我們知道 AOP 可以實(shí)現(xiàn)在方法開始執(zhí)行前后插入執(zhí)行我們想要的代碼,那這樣,我們是不是可以在執(zhí)行數(shù)據(jù)庫操作前根據(jù)業(yè)務(wù)來動(dòng)態(tài)切換數(shù)據(jù)源呢?

思考一下這個(gè)方式理論上好像是可行的,這種方式首先不需要在業(yè)務(wù)代碼中去做切換,二是可能以后我們不需要讀寫分離了,把 AOP 切換的代碼去掉就行了,三是可能就是拓展性好了。

等不了了,開始擼代碼

你可能想深入的了解的話,我這里給你幾個(gè)程序里用到的關(guān)鍵字enum(枚舉)annotation(自定義注解)JoinPoint(注入點(diǎn))AbstractRoutingDataSource(數(shù)據(jù)源接口子類),你理解了這些就知道了,其實(shí)你并不需要深入某些深層的東西,了解下即可。

一、建立JdbcContextHolder.java類

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class JdbcContextHolder {
 
 private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
 
 public static void setJdbcType(String jdbcType) {
 contextHolder.set(jdbcType);
 }
 
 public static void setSlave() {
 setJdbcType("slave");
 }
 
 public static void setMaster() {
 clearJdbcType();
 }
 
 public static String getJdbcType() {
 return (String) contextHolder.get();
 }
 
 public static void clearJdbcType() {
 contextHolder.remove();
 }
}

這個(gè)類的作用就是用來設(shè)置、獲取數(shù)據(jù)源連接

二、新建DynamicDataSource.java類,繼承于AbstractRoutingDataSource

?
1
2
3
4
5
6
7
8
9
10
11
12
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
 
import cn.mayongfa.common.JdbcContextHolder;
 
public class DynamicDataSource extends AbstractRoutingDataSource {
 
 @Override
 protected Object determineCurrentLookupKey() {
 // 獲取當(dāng)前數(shù)據(jù)源連接
 return JdbcContextHolder.getJdbcType();
 }
}

通過研究,我們知道determineCurrentLookupKey方法是獲取相關(guān)數(shù)據(jù)源連接的,所以重寫determineCurrentLookupKey方法就可以啦,然后我們?nèi)ネㄟ^剛剛我們建立的JdbcContextHolder類去獲取。那怎么設(shè)置呢?

三、建立數(shù)據(jù)源DataSourceType.java枚舉類

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public enum DataSourceType {
 
 //主庫
 Master("master"),
 
 //從庫
 Slave("slave");
 
 private DataSourceType(String name) {
 this.name = name;
 }
 
 private String name;
 
 public String getName() {
 return name;
 }
 public void setName(String name) {
 this.name = name;
 }
}

這個(gè)枚舉類的作用其實(shí)就是為了設(shè)置數(shù)據(jù)源而生的,它的目的就是讓設(shè)置數(shù)據(jù)源時(shí)更方便,如絲般順滑。

四、新建DataSource.java Annotation(自定義注解)類

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import java.lang.annotation.Documented;
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)
@Documented
public @interface DataSource {
 
 DataSourceType value() default DataSourceType.Master;
 
}

自定義注解的意義不再過多討論,一句話來說就是可以讓你在類或方法名上以打標(biāo)簽的形式讓該方法變得不一樣。具體怎么「不一樣」,這個(gè)在于你。

五、新建DataSourceChoose.java數(shù)據(jù)庫切換類

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import java.lang.reflect.Method;
 
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.MethodSignature;
 
import cn.mayongfa.common.JdbcContextHolder;
 
public class DataSourceChoose {
 
//方法執(zhí)行前
public void before(JoinPoint point){
 Object target = point.getTarget();
 String method = point.getSignature().getName();
 Class<?>[] classz = target.getClass().getInterfaces();
 MethodSignature methodSignature = (MethodSignature)point.getSignature();
 Class<?>[] parameterTypes = methodSignature.getMethod().getParameterTypes();
 try {
  Method m = classz[0].getMethod(method, parameterTypes);
  if (m!=null && m.isAnnotationPresent(DataSource.class)) {
  DataSource data = m.getAnnotation(DataSource.class);
  JdbcContextHolder.clearJdbcType();
  JdbcContextHolder.setJdbcType(data.value().getName());
  }
 } catch (Exception e) {
  // TODO: handle exception
 }
}
}

這個(gè)其實(shí)是一個(gè)攔截器類,主要作用就是攔截那些方法名上有@DataSource這個(gè)自定義注解的,完了根據(jù)獲取注解的value()值,來做相應(yīng)的數(shù)據(jù)源切換。

到這里,整個(gè)讀寫分離的分析及業(yè)務(wù)邏輯和具體代碼都完了,以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。

原文鏈接:http://www.cnblogs.com/mafly/p/master_slave.html

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 国产伦精品一区二区 | 洗濯屋H纯肉动漫在线观看 武侠艳妇屈辱的张开双腿 午夜在线观看免费观看 视频 | 深夜在线观看网站 | 舔比小说 | 日本成人免费在线视频 | 香蕉视频在线观看网址 | 国产东北3p真实在线456视频 | 深夜福利免费在线观看 | 2020韩国r级理论片在线观看 | 爱色v| 精品一久久香蕉国产线看播放 | 美女班主任让我爽了一夜视频 | 日本九九视频 | 日本漫画工囗全彩番在线 | 男女性潮高片无遮挡禁18 | 男人的天堂va | 97操| 免费国产在线观看 | 成人亚洲欧美日韩中文字幕 | 91素人约啪| 欧美成人tv在线观看免费 | 欧美久久久久久久一区二区三区 | 美女跪式抽搐gif动态图 | 亚洲成年网站在线777 | 精品久久久久久久久免费影院 | 毛片在线免费视频 | 亚洲天堂视频在线观看免费 | 四虎精品免费国产成人 | 亚洲激情自拍偷拍 | 啊皇上你好大要知画 | 日韩免费视频播放 | 短篇同学新婚h系列小说 | 99爱在线观看精品视频 | 蝴蝶传媒免费安装 | sao虎在线精品永久在线 | 黑人巨大videosjapan高清 黑人好大 | 午夜综合 | 6080窝窝理论 | 色噜噜狠狠色综合 | 久久久久久免费高清电影 | 国内精品 大秀视频 日韩精品 |