最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

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

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

原理

平常在使用Mysql的時(shí)候是通過(guò)JDBC的,得給一個(gè)url,userName,和password,如下:

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

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

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

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

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

再看Spring

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

解釋說(shuō)明

DriverManagerDataSource

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

AbstractRoutingDataSource

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

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

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

代碼分析

1.屬性

2.實(shí)現(xiàn)接口

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

3.重要方法

afterPropertiesSet

獲取Connection之前確定Key

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

determineCurrentLookupKey怎么來(lái)確定key呢?

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

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

 還有,一般都是用切面來(lái)操作ThreadLocal的

例子

我這里為了簡(jiǎn)單,就不寫切面了。直接代碼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);
	}
}

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

此外,之前說(shuō)了,動(dòng)態(tài)數(shù)據(jù)源里面有個(gè)map,它得需要數(shù)據(jù)源,此外還需要key,這里用bean的名字做為key,創(chuàng)建MyDynamicDataSource之后,設(shè)置TargetDataSources。當(dāng)MyDynamicDataSource被Spring創(chuàng)建的時(shí)候,InitializingBean#afterPropertiesSet()會(huì)通過(guò)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.動(dòng)態(tài)數(shù)據(jù)源實(shí)現(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.實(shí)體對(duì)象

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)建三個(gè)數(shù)據(jù)庫(kù),在三個(gè)數(shù)據(jù)庫(kù)里面都創(chuàng)建這個(gè)表,填寫點(diǎn)數(shù)據(jù)。

6.主要測(cè)試類

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); // 這里從頭到尾用的都是一個(gè)JdbcTemplate
			dataSource1(jdbcTemplate); // 動(dòng)態(tài)數(shù)據(jù)源1
			dataSource2(jdbcTemplate);// 動(dòng)態(tài)數(shù)據(jù)源2
			dataSource3(jdbcTemplate);// 動(dòng)態(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)容反映了我思考的過(guò)程,因?yàn)樗季S有限,不免有些內(nèi)容有出入,如果有問(wèn)題,歡迎指出。

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

相關(guān)文章

  • 如何在Spring Boot啟動(dòng)時(shí)運(yùn)行定制的代碼

    如何在Spring Boot啟動(dòng)時(shí)運(yùn)行定制的代碼

    在本文中您將學(xué)習(xí)如何掛鉤應(yīng)用程序引導(dǎo)程序生命周期并在Spring Boot啟動(dòng)時(shí)執(zhí)行代碼。文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2018-12-12
  • Java圖形化編程之JFrame疫苗接種系統(tǒng)詳解

    Java圖形化編程之JFrame疫苗接種系統(tǒng)詳解

    GUI圖形界面設(shè)計(jì)是用戶和程序交互的工具,用戶通過(guò)圖形界面控制程序事件的發(fā)生。首先介紹Swing的基本體系結(jié)構(gòu),這是底層
    2021-09-09
  • JAVA為什么要使用封裝及如何封裝經(jīng)典實(shí)例

    JAVA為什么要使用封裝及如何封裝經(jīng)典實(shí)例

    這篇文章主要給大家介紹了關(guān)于JAVA為什么要使用封裝及如何封裝的相關(guān)資料,封裝就是將屬性私有化,提供公有的方法訪問(wèn)私有屬性,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-10-10
  • Java日常練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(62)

    Java日常練習(xí)題,每天進(jìn)步一點(diǎn)點(diǎn)(62)

    下面小編就為大家?guī)?lái)一篇Java基礎(chǔ)的幾道練習(xí)題(分享)。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧,希望可以幫到你
    2021-08-08
  • Java多線程之ReentrantReadWriteLock源碼解析

    Java多線程之ReentrantReadWriteLock源碼解析

    這篇文章主要介紹了Java多線程之ReentrantReadWriteLock源碼解析,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java基礎(chǔ)的小伙伴們有非常好的幫助,需要的朋友可以參考下
    2021-05-05
  • 基于java構(gòu)造方法Vector修改元素源碼分析

    基于java構(gòu)造方法Vector修改元素源碼分析

    本篇文章是關(guān)于ava構(gòu)造方法Vector源碼分析系列文章,本文主要介紹了Vector修改元素的源碼分析,有需要的朋友可以借鑒參考下,希望可以有所幫助
    2021-09-09
  • Spring中的@Conditional注解實(shí)現(xiàn)分析

    Spring中的@Conditional注解實(shí)現(xiàn)分析

    這篇文章主要介紹了Spring中的@Conditional注解實(shí)現(xiàn)分析,  @Conditional是Spring 4出現(xiàn)的注解,但是真正露出價(jià)值的是Spring Boot的擴(kuò)展@ConditionalOnBean等,需要的朋友可以參考下
    2023-12-12
  • Java生成訂單號(hào)或唯一id的高并發(fā)方案(4種方法)

    Java生成訂單號(hào)或唯一id的高并發(fā)方案(4種方法)

    本文主要介紹了Java生成訂單號(hào)或唯一id的高并發(fā)方案,包括4種方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-01-01
  • 快速解決 MyBatis-Plus 中 ID 自增問(wèn)題(推薦)

    快速解決 MyBatis-Plus 中 ID 自增問(wèn)題(推薦)

    本文介紹了MyBatis-Plus中自動(dòng)生成ID過(guò)長(zhǎng)導(dǎo)致的問(wèn)題及解決方法,結(jié)合示例代碼給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧
    2025-02-02
  • java根據(jù)網(wǎng)絡(luò)地址保存圖片的方法

    java根據(jù)網(wǎng)絡(luò)地址保存圖片的方法

    這篇文章主要為大家詳細(xì)介紹了java根據(jù)網(wǎng)絡(luò)地址保存圖片的方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-07-07

最新評(píng)論

邻水| 抚宁县| 南宁市| 杨浦区| 曲沃县| 黔西县| 无极县| 沂水县| 昔阳县| 寿光市| 新巴尔虎左旗| 祁连县| 中方县| 河东区| 阿拉善盟| 张家港市| 会泽县| 罗田县| 镇原县| 沁源县| 瑞丽市| 偃师市| 霞浦县| 曲阳县| 永善县| 五大连池市| 古田县| 嵩明县| 长丰县| 凉城县| 垦利县| 旬阳县| 宝丰县| 眉山市| 婺源县| 新营市| 定陶县| 长白| 丰都县| 芷江| 七台河市|