基於註解和Spring的多數據源配置和使用

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



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章