基于注解和Spring的多数据源配置和使用

9 篇文章 0 订阅
4 篇文章 0 订阅

1.项目结构


2.所需Jar


3.定义名为DataSource的注解

package com.office.data.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * 定义名为DataSource的注解
 * @author Administrator
 *
 */
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface DataSource {
	String value();
}


4.动态数据源 

package com.office.data.source;

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
 * 动态数据源 
 * 实现spring 类方法AbstractRoutingDataSource.determineCurrentLookupKey 
 * 以更新数据源bean 
 * @author Administrator
 *
 */
public class DynamicDataSource extends AbstractRoutingDataSource{

	public final static String DEFAULT_DB="defaultDB";
	public final static String LOCAL_DB="localDB";
	@Override
	protected Object determineCurrentLookupKey() {
		//从自定义的位置获取数据源标识
		return DynamicDataSourceHolder.getDataSourceType();
	}

}

5.设置DB类型
package com.office.data.source;

public class DynamicDataSourceHolder {
	
	private static final ThreadLocal<String> contextHolder=new ThreadLocal<String>();
	
	/**
	 * 设置DB类型
	 * @param String
	 */
	public static void setDataSourceType(String String){
		contextHolder.set(String);
	}
	
	/**
	 * 获取DB类型
	 * @return
	 */
	public static String getDataSourceType(){
		return (String)contextHolder.get();
	}
	
	/**
	 * 清除DB类型
	 */
	public static void clearDataSourceType(){
		contextHolder.remove();
	}


}


6.定义AOP切面,以便拦截所有带@DataSource的方法

package com.office.data.intercept;

import java.lang.reflect.Method;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.MethodSignature;

import com.office.data.annotation.DataSource;
import com.office.data.source.DynamicDataSourceHolder;

/**
 * 定义AOP切面,以便拦截所有带@DataSource的方法
 * @author Administrator
 *
 */
public class DataSourceAspect {

	/**
	 * 拦截目标方法,获取由@DataSource指定的数据源标识,设置到线程存储中以便切换数据源
	 * @param point
	 * @throws Exception
	 */
	public void intercept(JoinPoint point)throws Exception{
		Class<?> target=point.getTarget().getClass();
		MethodSignature signature=(MethodSignature) point.getSignature();
		// 默认使用目标类型的注解,如果没有则使用其实现接口的注解
		for (Class<?> clazz:target.getInterfaces()) {
			resolveDataSource(clazz, signature.getMethod());
		}
		resolveDataSource(target, signature.getMethod());
	}
	
	/**
	 * 提取目标对象方法注解和类型注解中的数据源标识
	 * @param clazz
	 * @param method
	 */
	private void resolveDataSource(Class<?> clazz,Method method){
		try {
			Class<?>[] types=method.getParameterTypes();
			// 默认使用类型注解
			if(clazz.isAnnotationPresent(DataSource.class)){
				DataSource source=clazz.getAnnotation(DataSource.class);
				DynamicDataSourceHolder.setDataSourceType(source.value());
			}
			// 方法注解可以覆盖类型注解
			Method m=clazz.getMethod(method.getName(), types);
			if(m!=null&&m.isAnnotationPresent(DataSource.class)){
				DataSource source=m.getAnnotation(DataSource.class);
				DynamicDataSourceHolder.setDataSourceType(source.value());
			}
		} catch (Exception e) {
			System.out.println(clazz+":"+e.getMessage());
		} 
	}
	
}

7.定义实体

package com.office.data.entity;
/**
 * 定义实体
 * @author Administrator
 *
 */
public class TBook {
	private String idBook;// 图书ID

	private String name;// 图书名称

	private int number;// 馆藏数量

	public TBook() {
	}

	public String getIdBook() {
		return idBook;
	}

	public void setIdBook(String idBook) {
		this.idBook = idBook;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getNumber() {
		return number;
	}

	public void setNumber(int number) {
		this.number = number;
	}

	@Override
	public String toString() {
		return "TBook [idBook=" + idBook + ", name=" + name + ", number="
				+ number + "]";
	}

	public TBook(String idBook, String name, int number) {
		super();
		this.idBook = idBook;
		this.name = name;
		this.number = number;
	}

}

8.声明dao接口

package com.office.data.dao;

import java.util.List;

import com.office.data.entity.TBook;
/**
 * 
 * @author Administrator
 *
 */
public interface DataDao {
	
	List<TBook> getBaseList();
	
	List<TBook> getLocalList();
}

9.实现dao接口

package com.office.data.dao.impl;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.support.rowset.SqlRowSet;
import org.springframework.stereotype.Service;

import com.office.data.annotation.DataSource;
import com.office.data.dao.DataDao;
import com.office.data.entity.TBook;
import com.office.data.source.DynamicDataSource;

@Service
@DataSource(DynamicDataSource.DEFAULT_DB)
public class DataDaoImpl implements DataDao {
	@Autowired
	private JdbcTemplate jdbcTemplate;

	@Override
	public List<TBook> getBaseList() {
		return getBooks();
	}

	@Override
	@DataSource(DynamicDataSource.LOCAL_DB)
	public List<TBook> getLocalList() {
		return getBooks();
	}

	private List<TBook> getBooks() {
		List<TBook> books = new ArrayList<TBook>();
		String sql = "SELECT t.id_book,t.name,t.number FROM t_book t";
		SqlRowSet rs = jdbcTemplate.queryForRowSet(sql);
		while (rs.next()) {
			TBook book = new TBook();
			book.setIdBook(rs.getString(1));
			book.setName(rs.getString(2));
			book.setNumber(rs.getInt(3));
			books.add(book);
		}
		return books;
	}
	/*
	 * public JdbcTemplate getJdbcTemplate() { return jdbcTemplate; } public
	 * void setJdbcTemplate(JdbcTemplate jdbcTemplate) { this.jdbcTemplate =
	 * jdbcTemplate; }
	 */

}

10.spring配置文件 applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jdbc="http://www.springframework.org/schema/jdbc"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.2.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.2.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd">
	<!--==========================================================-->
	<!--=========================自动扫描=========================-->
	<!--==========================================================-->
	<context:annotation-config/>
	<context:component-scan base-package="com.office"/> 
	
	<!--==========================================================-->
	<!--========================导入属性文件=======================-->
	<!--==========================================================-->
	<context:property-placeholder location="classpath:config.properties"/>
	
	<!--==========================================================-->
	<!--======================配置数据源===========================-->
	<!--==========================================================-->
	<bean id="baseDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="username" value="${jdbc.username}"/>
		<property name="password" value="${jdbc.password}"/>
		<property name="driverClassName" value="${jdbc.driverClassName}"/>
		<property name="url" value="${jdbc.url}"/>
	</bean>
	
	
	<!--==========================================================-->
	<!--======================本地数据源配置=======================-->
	<!--==========================================================-->
	<bean id="localDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource" parent="baseDataSource">
		<property name="url" value="${local.url}"/>
	</bean>
	
	
	<bean id="dataSource" class="com.office.data.source.DynamicDataSource">
		<property name="targetDataSources">
			<!-- 指定lookupKey和与之对应的数据源 -->
			<map key-type="java.lang.String">
				<entry key="defaultDB" value-ref="baseDataSource"/>
				<entry key="localDB" value-ref="localDataSource"/>
			</map>
		</property>
		<!-- 指定默认的数据源 -->
		<property name="defaultTargetDataSource" ref="baseDataSource"/>
	</bean>
	
	<!--==========================================================-->
	<!--======================数据源拦截器=========================-->
	<!--==========================================================-->
	<bean id="dataSourceAspect" class="com.office.data.intercept.DataSourceAspect"/>
	<aop:config>
		<aop:aspect ref="dataSourceAspect">
			<!-- 拦截所有的Dao层方法 -->
			<aop:pointcut id="dataSourcePointcut" expression="execution(* com.office.data.dao.*.*(..))" />
			<aop:before pointcut-ref="dataSourcePointcut" method="intercept"/>
		</aop:aspect>
	</aop:config>
	
	
	<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource">
			<ref local="dataSource"/>
		</property>	
	</bean>
	
	<bean id="dataDao" class="com.office.data.dao.impl.DataDaoImpl"/>
	
</beans>

11.config.properties 配置文件

#********************************************
#******************Base JDBC*****************
#********************************************
jdbc.username=root
jdbc.password=root
jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://host1:3306/mydb

#********************************************
#******************Local JDBC****************
#********************************************
local.username=root
local.password=root
local.driverClassName=com.mysql.jdbc.Driver
local.url=jdbc:mysql://host2:3306/mydb

12.表SQL

/*
Navicat MySQL Data Transfer

Source Server         : MySql
Source Server Version : 50522
Source Host           : localhost:3306
Source Database       : mydb

Target Server Type    : MYSQL
Target Server Version : 50522
File Encoding         : 65001

Date: 2017-01-13 09:17:03
*/

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for t_book
-- ----------------------------
DROP TABLE IF EXISTS `t_book`;
CREATE TABLE `t_book` (
  `id_book` varchar(20) NOT NULL COMMENT '图书ID',
  `name` varchar(100) NOT NULL COMMENT '图书名称',
  `number` int(11) NOT NULL COMMENT '馆藏数量',
  PRIMARY KEY (`id_book`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='图书表';

-- ----------------------------
-- Records of t_book
-- ----------------------------
INSERT INTO `t_book` VALUES ('1000', 'Java程序设计', '3');
INSERT INTO `t_book` VALUES ('1001', '数据结构', '6');
INSERT INTO `t_book` VALUES ('1002', '设计模式', '10');
INSERT INTO `t_book` VALUES ('1003', '编译原理', '10');

13.测试类
package com.office.data;

import java.util.List;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.office.data.dao.DataDao;
import com.office.data.entity.TBook;
@SuppressWarnings("resource")
public class Main {

	public static void main(String[] args) {
		BeanFactory factory=new ClassPathXmlApplicationContext("applicationContext.xml");
		DataDao dataDao=(DataDao) factory.getBean("dataDao");
		List<TBook> books=dataDao.getBaseList();
		for (TBook tBook : books) {
			System.out.println(tBook);
		}
		System.out.println("===========================================");
		books=dataDao.getLocalList();
		for (TBook tBook : books) {
			System.out.println(tBook);
		}
	}
}

14.测试结果



最后附上源码下载地址:http://download.csdn.net/detail/after95/9736390



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值