• 使用Adivisor配置增强处理,来实现数据库读写分离


    一、先写一个demo来概述Adivisor的简单使用步骤

    实现步骤:

    1、通过MethodBeforeAdivice接口实现前置增强处理

     1 public class ServiceBeforeAdvisor implements MethodBeforeAdvice {
     2     private Logger logger = Logger.getLogger(ServiceBeforeAdvisor.class);
     3     @Override
     4     public void before(Method method, Object[] args, Object target)
     5             throws Throwable {
     6         logger.info("启动事务");
     7         logger.info("连接点对象:"+target.getClass().getSimpleName());
     8         logger.info("连接点方法:"+method.getName());
     9         logger.info("连接点方法参数:"+args[0]);
    10         
    11     }
    12     
    13 }

    2、使用<aop:advisor>标签织入增强处理

    1 //注意:advisor要放在aspect前面
    2     <bean id="userService" class="com.pb.service.UserService"></bean>
    3      <bean id="serviceBeforeAdvisor" class="com.pb.aop.ServiceBeforeAdvisor"></bean>
    4      <aop:config>
    5          <aop:pointcut expression="execution(public * com.pb.service.*.*(..))" 
    6                 id="servicePointcut"/>
    7          <aop:advisor advice-ref="serviceBeforeAdvisor" pointcut-ref="servicePointcut"/>
    8      </aop:config>

    3、测试类型

    1 public class Test {
    2     public static void main(String[] args) {
    3         ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext
    4                     ("applicationContext.xml");
    5         UserService service =  (UserService)context.getBean("userService");
    6         service.addUser(new User());
    7     }
    8 }

    二、使用Adivisor来实现数据读写分离

    实现步骤:

    1、通过MethodBeforeAdivice接口实现前置增强处理

     1 public class DataBaseAdvice implements MethodBeforeAdvice {
     2     /**
     3      * 日志计数器
     4      */
     5     private final static Logger logger = LoggerFactory.getLogger(DataBaseAdvice.class);
     6     /**
     7      * 存储方法前缀
     8      */
     9     private List<String> methodKey;
    10     /**
    11      * 是否打印日志:true-打印,false-不打印
    12      */
    13     private boolean showLog = true;
    14 
    15     public void before(Method method, Object[] objects, Object o) throws Throwable {
    16         boolean write = true;
    17         String methodName = method.getName().toLowerCase();
    18         //若方法前缀匹配成功,返回false
    19         if (CollectionUtils.isNotEmpty(methodKey)) {
    20             for (String key : methodKey) {
    21                 if (methodName.startsWith(key.toLowerCase())) {
    22                     write = false;
    23                     break;
    24                 }
    25             }
    26         }
    27 
    28         if (write) {
    29             DbContextHolder.setDbType(DbContextHolder.DB_TYPE_RW);
    30             if (showLog) {
    31                 logger.info(method.getName()+"连接主库");
    32             }
    33         }else {
    34             DbContextHolder.setDbType(DbContextHolder.DB_TYPE_R);
    35             if (showLog) {
    36                 logger.info(method.getName()+"连接从库");
    37             }
    38         }
    39     }
    40 
    41     public List<String> getMethodKey() {
    42         return methodKey;
    43     }
    44 
    45     public void setMethodKey(List<String> methodKey) {
    46         this.methodKey = methodKey;
    47     }
    48 
    49     public boolean isShowLog() {
    50         return showLog;
    51     }
    52 
    53     public void setShowLog(boolean showLog) {
    54         this.showLog = showLog;
    55     }
    56 }

    切换主从库的持有类

     1 public class DbContextHolder {
     2 
     3     /**
     4      * 线程threadLocal
     5      */
     6     private static ThreadLocal<String> contextHolder = new ThreadLocal<String>();
     7     /**
     8      * 主库:执行读写操作
     9      */
    10     public static String DB_TYPE_RW = "dataSourceMaster";
    11     /**
    12      * 从库:执行读库操作
    13      */
    14     public static String DB_TYPE_R = "dataSourceSlave";
    15 
    16     /**
    17      * 默认是读写库
    18      * @return
    19      */
    20     public static String getDbType() {
    21         String db = contextHolder.get();
    22         if (db == null) {
    23             db = DB_TYPE_RW;
    24         }
    25         return db;
    26     }
    27 
    28     /**
    29      * 置本线程的dbType
    30      * @param str
    31      */
    32     public static void setDbType(String str) {
    33         contextHolder.set(str);
    34     }
    35 
    36     /**
    37      * @Title: clearDBType
    38      * @Description: 清理连接类型
    39      */
    40     public static void clearDBType() {
    41         contextHolder.remove();
    42     }
    43 }

    2、使用<aop:advisor>标签织入增强处理

     1 <!-- 动态数据源 -->
     2     <bean id="dynamicDataSource" class="com.alibaba.health.dao.dynamic.DynamicDataSource">
     3         <!-- 通过key-value关联数据源 -->
     4         <property name="targetDataSources">
     5             <map>
     6                 <entry value-ref="dataSourceMaster" key="monitorDataSourceMaster"/>
     7                 <entry value-ref="dataSourceSlave" key="monitorDataSourceSlave"/>
     8             </map>
     9         </property>
    10         <property name="defaultTargetDataSource" ref="dataSourceMaster"/>
    11     </bean>
    12 
    13 <!-- 通知器的具体实现:配置主从库读写分离:以select、query、find、count开头的方法走从库 -->
    14     <bean id="DataBaseAdvice" class="com.aliaba.health.dao.dynamic.DataBaseAdvice">
    15         <property name="methodKey">
    16             <list>
    17                 <value>select</value>
    18                 <value>query</value>
    19                 <value>find</value>
    20                 <value>count</value>
    21             </list>
    22         </property>
    23         <property name="showLog" value="false"/>
    24     </bean>
    25 
    26     <!-- 切面配置 -->
    27     <aop:config>
    28         <!-- 配置切点:第一个*表示匹配所有方法的返回值类型,.表示当前包下所有类的方法,..表示当前包下及此包下所有自爆中的所有类方法;
    29              第二个*表示所有类名,第三个*表示所有方法名,(..)表示所有方法参数-->
    30         <aop:pointcut expression="execution(* com.alibaba.health.dao..*.*(..))" id="cutPoint"/>
    31         <!-- 定义通知器 -->
    32         <aop:advisor advice-ref="DataBaseAdvice" pointcut-ref="cutPoint"/>
    33     </aop:config>

    此时就完成了主从数据库读写分离的代码和xml配置,尤其可见各种技术组件,在于是否能灵活运用。

  • 相关阅读:
    性能测试工具LoadRunner11-LR之Virtual User Generator 移动app录制
    性能测试工具LoadRunner10-LR之Virtual User Generator 错误处理函数
    性能测试工具LoadRunner09-LR之Virtual User Generator 日志
    解决粘包-简单版本
    关于三级菜单
    Python学习的第二天
    CSS选择器的权重与优先规则
    keydown/keypress/keyup
    APICloud 实现 使用openFrameGroup引入页面后禁止上下滑动
    WampServer 3.0.6 服务器端配置
  • 原文地址:https://www.cnblogs.com/aoshicangqiong/p/11603470.html
Copyright © 2020-2023  润新知