欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Spring中的動態(tài)數(shù)據(jù)源解讀

 更新時間:2023年06月27日 09:16:24   作者:daliucheng  
這篇文章主要介紹了關(guān)于Spring中的動態(tài)數(shù)據(jù)源解讀,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

動態(tài)數(shù)據(jù)源的原理得先說清。

原理

平常在使用Mysql的時候是通過JDBC的,得給一個url,userName,和password,如下:

jdbc:mysql://localhost:3306/t_db1?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC

一個url對應(yīng)一個Connection對象,需要在url中指定需要連接的庫。

之后的Mysql的CRUD的操作都是通過Connection對象來做的。所以,動態(tài),就是在這個時候操作的,在獲取Connection的時候來通過指定的key來判斷要用哪個數(shù)據(jù)源。這得有一個前提,得先建立Connection,之后在獲取Connection的時候在判斷,

1.通過什么判斷呢?存放key和Connection的數(shù)據(jù)結(jié)構(gòu)是什么?

只要指定一個回調(diào)方法,key隨便,存放key和Connection的數(shù)據(jù)結(jié)構(gòu)是Map。在獲取Connection的時候,先確定Key,在獲取Connection就好了。

再看Spring

Java連接Mysql指定了接口,需要實現(xiàn)DataSource接口,Spring中提供了抽象類(AbstractDataSource

解釋說明

DriverManagerDataSource

這個沒有什么可說,只是封裝了一下連接mysql需要用的一些屬性,比如userName,password,url,driver,就是就老一套的獲取Connection封裝了一下

AbstractRoutingDataSource

Spring提供的動態(tài)數(shù)據(jù)源的抽象類

首先,它里面有一個Map,Map的key是Object(這是自定義的),V是Object(雖然是Object,代碼里面規(guī)定了,只能為String,和DataSource),其實它本質(zhì)就應(yīng)該是DataSource,這里是String的目的是為了可以通過DataSourceLookup來獲取數(shù)據(jù)源。(比如,可以在配置數(shù)據(jù)源的時候,直接配置數(shù)據(jù)源的bean的名字,然后自己寫一個DataSourceLookup的實現(xiàn)類,從BeanFactory中獲取DataSource)。

還提供了一個determineCurrentLookupKey()方法來判斷當(dāng)前數(shù)據(jù)源的key,其實就是map中的key。在最終獲取Connection的時候通過當(dāng)前的key獲取DataSource,在通過DataSource獲取真正的Connection。

代碼分析

1.屬性

2.實現(xiàn)接口

實現(xiàn)了InitializingBean那它肯定在afterPropertiesSet會做操作。等會看看

3.重要方法

afterPropertiesSet

獲取Connection之前確定Key

 `determineCurrentLookupKey`方法是留給子類拓展的。

determineCurrentLookupKey怎么來確定key呢?

它是一個無參的方法,一般來說,都是放在ThreadLocal中,在執(zhí)行sql操作之前,在對應(yīng)的ThreadLocal放這次需要的key,就可以在determineCurrentLookupKey中獲取ThreadLocal中的值,確定key。

 <font color='red'>Spring提供了一個動態(tài)數(shù)據(jù)源的實現(xiàn)類,`IsolationLevelDataSourceRouter`,key是事務(wù)的隔離級別。意思就是可以根據(jù)不同的隔離級別來選擇DataSource</font>

 還有,一般都是用切面來操作ThreadLocal的

例子

我這里為了簡單,就不寫切面了。直接代碼cv。

1.配置類

package datasource.dynamic;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class Config {
	@Bean
	public DriverManagerDataSource dataSource1(){
		String url = "jdbc:mysql://localhost:3306/t_db1?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC";
		String userName = "root";
		String password = "123456";
		return new DriverManagerDataSource(url,userName,password);
	}
	@Bean
	public DriverManagerDataSource dataSource2(){
		String url = "jdbc:mysql://localhost:3306/t_db2?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC";
		String userName = "root";
		String password = "123456";
		return new DriverManagerDataSource(url,userName,password);
	}
	@Bean
	public DriverManagerDataSource dataSource3(){
		String url = "jdbc:mysql://localhost:3306/t_db3?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC";
		String userName = "root";
		String password = "123456";
		return new DriverManagerDataSource(url,userName,password);
	}
	@Bean
	public MyDynamicDataSource dynamicDataSource(Map<String,DriverManagerDataSource> map){
		HashMap<Object, Object> original = new HashMap<>(map);
		MyDynamicDataSource myDynamicDataSource = new MyDynamicDataSource();
		myDynamicDataSource.setTargetDataSources(original);
		return myDynamicDataSource;
	}
	@Bean
	public JdbcTemplate jdbcTemplate(AbstractRoutingDataSource dataSource){
		return new JdbcTemplate(dataSource);
	}
}

配置了三個數(shù)據(jù)庫,也就是三個數(shù)據(jù)源,利用JdbcTemplate來快捷的執(zhí)行sql,JdbcTemplate需要指定用自己定義的動態(tài)數(shù)據(jù)源(MyDynamicDataSource)。

此外,之前說了,動態(tài)數(shù)據(jù)源里面有個map,它得需要數(shù)據(jù)源,此外還需要key,這里用bean的名字做為key,創(chuàng)建MyDynamicDataSource之后,設(shè)置TargetDataSources。當(dāng)MyDynamicDataSource被Spring創(chuàng)建的時候,InitializingBean#afterPropertiesSet()會通過DataSourceLookup轉(zhuǎn)換。

2.ThreadLocal

package datasource.dynamic;
import org.springframework.util.Assert;
public class DataSourceKeyHolder {
	private static final ThreadLocal<String> keyHolder = new ThreadLocal<>();
	public static void setKey(String key) {
		keyHolder.remove();
		keyHolder.set(key);
	}
	public static String getKey() {
		String s = keyHolder.get();
		Assert.notNull(s, "key 不能為空");
		return s;
	}
	public static void clear(){
		keyHolder.remove();
	}
}

3.動態(tài)數(shù)據(jù)源實現(xiàn)類

package datasource.dynamic;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
public class MyDynamicDataSource extends AbstractRoutingDataSource {
	@Override
	protected Object determineCurrentLookupKey() {
		return DataSourceKeyHolder.getKey();
	}
}

只是從ThreadLocal中獲取當(dāng)前的key就好了。

4.實體對象

public class TestBean {
	private Integer id;
	private String name;
	private Double age;
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Double getAge() {
		return age;
	}
	public void setAge(Double age) {
		this.age = age;
	}
	@Override
	public String toString() {
		return "TestBean{" +
				"id=" + id +
				", name='" + name + '\'' +
				", age=" + age +
				'}';
	}
}

5.sql

-- auto-generated definition
create table t_test
(
    id   int auto_increment
        primary key,
    name text   null,
    age  double null
);

創(chuàng)建三個數(shù)據(jù)庫,在三個數(shù)據(jù)庫里面都創(chuàng)建這個表,填寫點數(shù)據(jù)。

6.主要測試類

package datasource.dynamic;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
public class MainTest {
	public static void main(String[] args) {
		try {
			AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
			JdbcTemplate jdbcTemplate = context.getBean(JdbcTemplate.class); // 這里從頭到尾用的都是一個JdbcTemplate
			dataSource1(jdbcTemplate); // 動態(tài)數(shù)據(jù)源1
			dataSource2(jdbcTemplate);// 動態(tài)數(shù)據(jù)源2
			dataSource3(jdbcTemplate);// 動態(tài)數(shù)據(jù)源3
		}catch (Exception e){
			e.printStackTrace();
		}
	}
	public static void dataSource1(	JdbcTemplate jdbcTemplate ){
		DataSourceKeyHolder.setKey("dataSource1");
		try {
			TestBean testBean = jdbcTemplate.queryForObject("select * from t_test where id=?", new BeanPropertyRowMapper<>(TestBean.class), 1);
			System.out.println(testBean);
		}finally {
			DataSourceKeyHolder.clear();
		}
	}
	public static void dataSource2(	JdbcTemplate jdbcTemplate ){
		DataSourceKeyHolder.setKey("dataSource2");
		try {
			TestBean testBean = jdbcTemplate.queryForObject("select * from t_test where id=?", new BeanPropertyRowMapper<>(TestBean.class), 1);
			System.out.println(testBean);
		}finally {
			DataSourceKeyHolder.clear();
		}
	}
	public static void dataSource3(	JdbcTemplate jdbcTemplate ){
		DataSourceKeyHolder.setKey("dataSource3");
		try {
			TestBean testBean = jdbcTemplate.queryForObject("select * from t_test where id=?", new BeanPropertyRowMapper<>(TestBean.class), 1);
			System.out.println(testBean);
		}finally {
			DataSourceKeyHolder.clear();
		}
	}
}

7.結(jié)果

總結(jié)

關(guān)于這篇文章,我是把它當(dāng)做我的筆記,里面有很多的內(nèi)容反映了我思考的過程,因為思維有限,不免有些內(nèi)容有出入,如果有問題,歡迎指出。

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Netty序列化深入理解與使用

    Netty序列化深入理解與使用

    序列化 (Serialization)是將對象的狀態(tài)信息轉(zhuǎn)換為可以存儲或傳輸?shù)男问降倪^程。在序列化期間,對象將其當(dāng)前狀態(tài)寫入到臨時或持久性存儲區(qū)。以后,可以通過從存儲區(qū)中讀取或反序列化對象的狀態(tài),重新創(chuàng)建該對象
    2022-08-08
  • Spring整合消息隊列RabbitMQ流程

    Spring整合消息隊列RabbitMQ流程

    Spring整合RabbitMQ很容易,但是整合的目的是為了使用,那要使用RabbitMQ就要對其有一定的了解,不然容易整成一團漿糊。因為說到底,Spring只是在封裝RabbitMQ的API,讓其更容易使用而已,廢話不多說,讓我們一起整它
    2023-03-03
  • spring源碼閱讀--aop實現(xiàn)原理講解

    spring源碼閱讀--aop實現(xiàn)原理講解

    這篇文章主要介紹了spring源碼閱讀--aop實現(xiàn)原理講解,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • JVM與操作系統(tǒng)之間的關(guān)系詳解

    JVM與操作系統(tǒng)之間的關(guān)系詳解

    JVM與操作系統(tǒng)之間是依賴與被依賴的關(guān)系,JVM依賴于操作系統(tǒng)提供的資源和服務(wù),同時JVM也起到了抽象與隔離的作用,為Java程序提供了一個統(tǒng)一的、與平臺無關(guān)的運行環(huán)境,提高了Java程序的安全性
    2025-03-03
  • Java單例模式實現(xiàn)靜態(tài)內(nèi)部類方法示例

    Java單例模式實現(xiàn)靜態(tài)內(nèi)部類方法示例

    這篇文章主要介紹了Java單例模式實現(xiàn)靜態(tài)內(nèi)部類方法示例,涉及構(gòu)造函數(shù)私有化等相關(guān)內(nèi)容,需要的朋友可以了解下。
    2017-09-09
  • 詳解JNI到底是什么

    詳解JNI到底是什么

    JNI是Java Native Interface的縮寫,通過使用 Java本地接口書寫程序,可以確保代碼在不同的平臺上方便移植。從Java1.1開始,JNI標(biāo)準(zhǔn)成為java平臺的一部分,它允許Java代碼和其他語言寫的代碼進行交互
    2021-06-06
  • Java如何實現(xiàn)登錄token令牌

    Java如何實現(xiàn)登錄token令牌

    這篇文章主要介紹了Java如何實現(xiàn)登錄token令牌,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-05-05
  • Java中ClassLoader類加載學(xué)習(xí)總結(jié)

    Java中ClassLoader類加載學(xué)習(xí)總結(jié)

    本篇文章主要給大家講述了Java中ClassLoader類加載的原理以及用法總結(jié),一起學(xué)習(xí)下。
    2017-12-12
  • IDEA 當(dāng)前在線人數(shù)和歷史訪問量的示例代碼

    IDEA 當(dāng)前在線人數(shù)和歷史訪問量的示例代碼

    這篇文章主要介紹了IDEA 當(dāng)前在線人數(shù)和歷史訪問量的實例代碼,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-08-08
  • 關(guān)于SpringBoot改動后0.03秒啟動的問題

    關(guān)于SpringBoot改動后0.03秒啟動的問題

    這篇文章主要介紹了SpringBoot改動后0.03秒啟動,本文結(jié)合示例代碼給大家講解的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-12-12

最新評論