2數據讀寫分離(aop方式)

使用到技術 aop 註解java

1.先看spring中Datasource類spring

public interface DataSource extends CommonDataSource,Wrapper {sql

Connection getConnection() throws SQLException;express

Connection getConnection(String username, String password) throws SQLException;apache

}tomcat

兩個方法都是獲得鏈接的。在看下AbstractRoutingDataSource是怎麼實現DataSource接口mybatis

public Connection getConnection() throws SQLException {app

return determineTargetDataSource().getConnection();ide

}字體

public Connection getConnection(String username, String password) throws SQLException {

return determineTargetDataSource().getConnection(username, password);

}

很明顯是使用determineTargetDataSource()方法獲取到的connection。determineTargetDataSource方法定義以下:

private Map<Object, DataSource> resolvedDataSources;

protected DataSource determineTargetDataSource() {

Assert.notNull(this.resolvedDataSources, "DataSource router not initialized");

Object lookupKey = determineCurrentLookupKey();

DataSource dataSource = this.resolvedDataSources.get(lookupKey);

if (dataSource == null && (this.lenientFallback || lookupKey == null)) {

dataSource = this.resolvedDefaultDataSource;

}

if (dataSource == null) {

throw new IllegalStateException("Cannot determine target DataSource for lookup key [" + lookupKey + "]");

}

return dataSource;

}

protected abstract Object determineCurrentLookupKey();

很顯然是上面加粗字體獲得的數據源;

resolvedDataSources數據類型是map,能夠把masterDatasource 跟 slaveDatasource存到map中

而後寫一個類DynamicDataSource繼承AbstractRoutingDataSource,實現determineCurrentLookupKey()方法,該方法返回map的key,master或者slave就能夠了。

 

2.具體實現:

//添加註解方式

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.METHOD)

public @interface DataSource {

String value();

}

//動態獲取數據源類 繼承 AbstractRoutingDataSource 實現他裏面的抽象方法返回master或者slave

public class DynamicDataSource extends AbstractRoutingDataSource {

@Override

protected Object determineCurrentLookupKey() {

// TODO Auto-generated method stub return DynamicDataSourceHolder.getDataSouce();

}

}

//建立線程獲取註解獲得的數據源

public class DynamicDataSourceHolder {

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

public static void putDataSource(String name) {

holder.set(name);

}

public static String getDataSouce() {

return holder.get();

}

}

//下面是核心部分,aop

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()) .getMethod().getParameterTypes();

try {

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

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

DataSource data = m .getAnnotation(DataSource.class); DynamicDataSourceHolder.putDataSource(data.value());

System.out.println(data.value());

}

}

catch (Exception e) { // TODO: handle exception } } }

// 重點 配置文件使用

<!--主數據源 能夠使用讀取jdbc -->

<!-- 數據源配置 master-->

<bean id="masterDataSource" destroy-method="close" class="org.apache.tomcat.dbcp.dbcp2.BasicDataSource">

<property name="driverClassName" value="${jdbc.driver.master}" />

<property name="url" value="${jdbc.url.master}" />

<property name="username" value="${jdbc.username.master}" />

<property name="password" value="${jdbc.password.master}" />

</bean>

<!-- 數據源配置 slave-->

<bean id="slaveDataSource" destroy-method="close" class="org.apache.tomcat.dbcp.dbcp2.BasicDataSource">

<property name="driverClassName" value="${jdbc.driver.slave}" />

<property name="url" value="${jdbc.url.slave}" />

<property name="username" value="${jdbc.username.slave}" />

<property name="password" value="${jdbc.password.slave}" />

</bean>

 

下劃線部分須要添加 xmlns:beans="http://www.springframework.org/schema/beans" 頭部空間文件 否則會報錯

<!-- 數據源的得到 -->

<beans:bean id="dataSource" class="com.rainbow.base.common.DynamicDataSource">

<property name="targetDataSources">

<map key-type="java.lang.String">

<!-- write -->

<entry key="master" value-ref="masterDataSource"/>

<!-- read -->

<entry key="slave" value-ref="slaveDataSource"/>

</map>

</property>

<property name="defaultTargetDataSource" ref="masterDataSource"/>

</beans:bean>

 

<!-- 配置事務管理器 -->

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

<property name="dataSource" ref="dataSource" />

</bean>

<!-- 配置AOP切面 這裏我選擇切點是service 由於service切面能夠控制好事務 -->

<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

<beans:bean id="manyDataSourceAspect" class="com.rainbow.base.common.DataSourceAspect" />

<aop:config>

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

<aop:pointcut id="tx" expression="execution(* com.rainbow.*.service.*.*(..))"/>

<aop:before pointcut-ref="tx" method="before"/>

</aop:aspect>

</aop:config>

 

<!-- mybatis集成配置 -->

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">

<property name="dataSource" ref="dataSource" />

<property name="configLocation" value="classpath:conf/mybatis/mybatis-config.xml" />

<property name="mapperLocations">

<list>

<value>classpath*:conf/mybatis/mappers/**/*.xml</value>

</list>

</property>

</bean>

相關文章
相關標籤/搜索