第九章 springboot + mybatis + 多數據源 (AOP實現),springbootmybatis
在第八章 springboot + mybatis + 多數據源代碼的基礎上,做兩點修改
1、ShopDao

![]()
1 package com.xxx.firstboot.dao;
2
3 import org.springframework.beans.factory.annotation.Autowired;
4 import org.springframework.stereotype.Repository;
5
6 import com.xxx.firstboot.domain.Shop;
7 import com.xxx.firstboot.mapper.ShopMapper;
8
9 @Repository
10 public class ShopDao {
11 @Autowired
12 private ShopMapper mapper;
13
14 /**
15 * 獲取shop
16 */
17 public Shop getShop(int id) {
18 return mapper.getShop(id);
19 }
20 }
View Code
說明:只是去掉了設置數據源key的那一句代碼
2、DataSourceAspect

![]()
1 package com.xxx.firstboot.common.datasource;
2
3 import org.aspectj.lang.JoinPoint;
4 import org.aspectj.lang.annotation.Aspect;
5 import org.aspectj.lang.annotation.Before;
6 import org.springframework.stereotype.Component;
7
8 import com.xxx.firstboot.dao.ShopDao;
9
10 @Aspect
11 @Component
12 public class DataSourceAspect {
13
14 @Before("execution(* com.xxx.firstboot.dao.*.*(..))")
15 public void setDataSourceKey(JoinPoint point){
16 //連接點所屬的類實例是ShopDao
17 if(point.getTarget() instanceof ShopDao){
18 DatabaseContextHolder.setDatabaseType(DatabaseType.mytestdb2);
19 }else{//連接點所屬的類實例是UserDao(當然,這一步也可以不寫,因為defaultTargertDataSource就是該類所用的mytestdb)
20 DatabaseContextHolder.setDatabaseType(DatabaseType.mytestdb);
21 }
22 }
23
24 // @Around("execution(* com.xxx.firstboot.dao.*.*(..))")
25 // public Object setDataSourceKeyByAround(ProceedingJoinPoint point) throws Throwable{
26 // if(point.getTarget() instanceof ShopDao){
27 // DatabaseContextHolder.setDatabaseType(DatabaseType.mytestdb2);
28 // }else{//連接點所屬的類實例是UserDao(當然,這一步也可以不寫,因為defaultTargertDataSource就是該類所用的mytestdb)
29 // DatabaseContextHolder.setDatabaseType(DatabaseType.mytestdb);
30 // }
31 // return point.proceed();//執行目標方法
32 // }
33
34 }
View Code
說明:列出了兩種切面方法,在這裡推薦使用前者,原因:
- @Around:需要寫執行目標方法的那一行代碼,而這一行代碼可能會拋異常,還需要拋出或捕獲
對於切點表達式,可以抽取出來,進行重復利用。如上代碼可以改為如下:

![]()
1 package com.xxx.firstboot.common.datasource;
2
3 import org.aspectj.lang.JoinPoint;
4 import org.aspectj.lang.annotation.Aspect;
5 import org.aspectj.lang.annotation.Before;
6 import org.aspectj.lang.annotation.Pointcut;
7 import org.springframework.stereotype.Component;
8
9 import com.xxx.firstboot.dao.ShopDao;
10
11 @Aspect
12 @Component
13 public class DataSourceAspect {
14
15 /**
16 * 使用空方法定義切點表達式
17 */
18 @Pointcut("execution(* com.xxx.firstboot.dao.*.*(..))")
19 public void declareJointPointExpression() {
20 }
21
22 /**
23 * 使用定義切點表達式的方法進行切點表達式的引入
24 */
25 @Before("declareJointPointExpression()")
26 public void setDataSourceKey(JoinPoint point) {
27 // 連接點所屬的類實例是ShopDao
28 if (point.getTarget() instanceof ShopDao) {
29 DatabaseContextHolder.setDatabaseType(DatabaseType.mytestdb2);
30 } else {// 連接點所屬的類實例是UserDao(當然,這一步也可以不寫,因為defaultTargertDataSource就是該類所用的mytestdb)
31 DatabaseContextHolder.setDatabaseType(DatabaseType.mytestdb);
32 }
33 }
34
35 }
View Code
注意:該切點表達式也可以用在其他切面類中,引入的時候使用"全類名.切點方法名()",例:@Before("com.xxx.firstboot.common.datasource.DataSourceAspect.declareJointPointExpression()")
關於AOP,查看:第一章 AOP