zoukankan      html  css  js  c++  java
  • Spring aop读写分离

    一、采用读写分离技术的目标

           随着网站的业务不断扩展,数据不断增加,用户越来越多,数据库的压力也就越来越大,采用传统的方式,比如:数据库或者SQL的优化基本已达不到要求,这个时候可以采用读写分离的策略来改变现状。采用读写分离技术能够有效减轻Master库的压力,又可以把用户查询数据的请求分发到不同的Slave库,从而保证系统的健壮性。

    二、常用的两种方式

        1、定义两个数据库链接,一个是masterDataSource,另个是slaveDataSource,更新数据时读取masterDataSource,查询是读取slaveDataSource。

         2、动态数据源切换,在程序运行时,把数据源动态织如入程序中,从而选择主库还是从库。主要技术采用annotation,Spring AOP,反射,接下来详细介绍该种方法。

    三、动态数据源切换实现读写分离

     1,定义DataSource注解

    @Retention(RetentionPolicy.RUNTIME)  

    @Target(ElementType.METHOD)

    public @interface DataSource {

     String value(); 

    }

    2,继承抽象类AbstractRoutingDataSource来实现DynamicDataSource方法 

    public class DynamicDataSource extends AbstractRoutingDataSource{ 

     public static final Logger logger = Logger.getLogger(DynamicDataSource.class.toString()); 

     @Override

        protected Object determineCurrentLookupKey() {

             return DynamicDataSourceHolder.getDataSource();

        }

    }

    3,定义DynamicDataSourceHolder方法

     public class DynamicDataSourceHolder {

      private static final ThreadLocal<String> holder = new ThreadLocal<String>();

         public static void setDataSource(String name) {

             holder.set(name);

         }

         public static String getDataSource() {

             return holder.get();

         }  

    }

    4,定义DataSourceAspect类,在程序运行时动态切换数据源

    public class DataSourceAspect {  

        public void before(JoinPoint point){  

            Object target = point.getTarget();   

            String method = point.getSignature().getName();   

            Class<?>[] classz = target.getClass().getInterfaces();  

            Class<?>[] parameterTypes = ((MethodSignature)point.getSignature()).getParameterTypes();  

            try{  

                Method m = classz[0].getMethod(method, parameterTypes);  

                if(m != null && m.isAnnotationPresent(DataSource.class)){  

                    DataSource date = m.getAnnotation(DataSource.class);  

                    DynamicDataSourceHolder.setDataSource(date.value());  

                }  

                else {

                    // 默认master

                    DynamicDataSourceHolder.setDataSource("master");

                }

            }catch(Exception e){               

            }  

        }  

    }

    5,applicationContext-dataSource.xml配置

      分别定义主从数据源后,再添加选择数据源的bean

    <bean id="dataSource" class="****">

     <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>

    增加aop配置

    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>      <bean id="manyDataSourceAspect" class="****.DataSourceAspect" />  

        <aop:config>  

            <aop:aspect id="c" ref="manyDataSourceAspect">  

                <aop:before method="before" pointcut="execution(* *****.data.dao.*.*(..))"></aop:before>  

            </aop:aspect>  

        </aop:config>  

    6,DAO层定义方法的数据源

    @DataSource(value="slave")

     public ImUser findById(int id);

  • 相关阅读:
    BAT脚本打印空行的使用方法
    Shell脚本关于屏幕输出的字符进行颜色控制的问题
    shell脚本中切换用户执行相应的命令或者shell脚本的方法
    Linux下执行的java命令重定向到文件中的方法
    解决Firefox浏览器每次打开都弹出导入向导的问题
    解决Ruby在IE11中报Unable to get browser (Selenium::WebDriver::Error::NoSuchWindowError)的错误
    6月28日 Django form组件 和 modelform组件
    6月27日 ajax
    6月25日 Django 分页 cookie、session
    6月26日 Django 中间件
  • 原文地址:https://www.cnblogs.com/jiangxiaoyaoblog/p/5600814.html
Copyright © 2011-2022 走看看