目的: 使用Spring的AOP实现 数据库的 读写分离。
研究
.1. 数据库读写分离,将会有多个数据源,比如 slaveDataSource,masterDataSource
.2. 自定义个@DataSource接口,直接在相应的方法上面注入 @DataSource(value=”master”) 或者 @DataSource(value=”slave”) 进行区分
.3. 发现直接用@Aspect的@Before不行,因为在项目中使用了@Transational
原因:
Spring中的事务跟数据库中的事务相对应,所以也可以回滚,提交。 在开始事务之前,会先获取数据源,连接数据库,所以在@Aspect中的@Before中进行相关操作就晚了,具体可以在 TransactionAspectSupport::invokeWithinTransaction 中设置断点进行观察。这一切都是在TransactionInterceptor 进行的
.4. 所以,最后的方式有两个解决方案
4.1. 方案一: 采用对切面分配 Order,让他们先后执行
4.2. 方案二: 自定义一个 TransactionInterceptor,在里面进行数据源的确定
aspectj-autoproxy 简单介绍
在spring的配置文件中,配置了如下:
<context:annotation-config />
<aop:aspectj-autoproxy proxy-target-class="true" />
aspectj-autoproxy 是配置切面的。 @Transactional 跟 @Aspect 都是切面,即都是AOP,所以都会自动代理,生成相应的代理类
proxy-target-class="true"
该属性的配置的主要作用是在生成代理的时候,采用哪种代理方式:
1. 当被代理对象的是一个 类时,采用CGLIB的方式生成代理
2. 当被代理对象是一个 接口时,采用JDK的动态代理方式生成代理
如果没有该属性,所有的代理方式都是JDK的动态代理方式
源码如下:
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
if (targetClass.isInterface()) {
return new JdkDynamicAop