spring多数据源

一。目的

在组内方便的切换主库和从库

二。具体做法

代码部分改动

1. 增加了一个注解DataSourceChange

public @interface DataSourceChange {

    boolean fromSlave() default false;

}

2. 增加了MultipleDataSourceInterceptor

在这个函数里,利用AOP,将当前的DataSourceNameContextHolder 切换到从库上

主要需要关注的代码是

   //为了减少影响面,目前只对×Service类里拥有DataSourceChange注解方法 进行AOP

    private final static String EDP = "execution(@com.DataSourceChange * com" +

            "..*Service.*(..))";

  

   // 这是切换DataSourceNameContextHolder的部分代码

     try {

            if (fromSlave) {

                DataSourceNameContextHolder.set(DataSourceNameConstant.SLAVE);

            }

            obj = joinPoint.proceed(args);

        } catch (Throwable e) {

            e.printStackTrace();

        } finally {

            if (fromSlave) {

                DataSourceNameContextHolder.clear();

            }

        }

3.增加了一个Wrapper

将原来ProductDao的部分方法挪了出来,放在这里,使用方法

    @DataSourceChange(fromSlave = true)

    public List<String> getIncludeSupplierIds() {

        return xxDao.getIncludeSupplierIds();

    }

三。验证方法

打开spring连接transaction的日志,查看使用了哪个连接。

四。结论

1. 如何使用

如果想让某个由Spring管理的Service里的某个方法访问从库,只需要给Service加上注解 @DataSourceChange(fromSlave = true), 则这个Service里的方法会自动访问从库。(前提是,Service里的DAO是由spring+mybatis管理的).

譬如

    @DataSourceChange(fromSlave = true)

    public List<String> fooA() {

        return xxx.fooA();

    }

2. 不足

我尝试过,将这个注解加到DAO这一层,譬如

@Repository

public interface xxDao {

     @DataSourceChange(fromSlave = true)

    List<String> fooA();

}

启动时Spring会报错,提示 Could not generate CGLIB subclass of final class.

猜测原因可能是 mybatis 自动生成Mapper类时,使用了CGLIB。 但是在spring再对这个interface进行代理时,必须用JDK默认的proxy才行。。所以这里可能会有冲突。 

还希望有别的同学能来指导具体的原因

如果这个service有@Transaction注解时,也不能使用这种方法。。。 这好像是Spring的一个bug,使用Transaction时,只会使用默认的dataSource

(已经由组内其他同事解决了。)

猜你喜欢

转载自gambol1234.iteye.com/blog/2088622