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

spring注解 @PropertySource配置數(shù)據(jù)源全流程

 更新時間:2022年03月25日 17:10:36   作者:zrk1000  
這篇文章主要介紹了spring注解 @PropertySource配置數(shù)據(jù)源全流程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

@PropertySource數(shù)據(jù)源配置

一般在配置數(shù)據(jù)源是都會使用xml的方式注入,key-value在properties中管理;spring4.X已有著比較完善的注解來替換xml的配置方式。

使用xml配置數(shù)據(jù)源

通常我們使用xml配置數(shù)據(jù)源,使用SpEL獲取properties中的配置。

applicationContext.xml 中配置 dataSource 及 PreferencesPlaceholderConfigurer,使用 PropertyPlaceholderConfigurer進(jìn)行Bean屬性替換

<bean id="configProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
? ? ? ? <property name="locations">
? ? ? ? ? ? <list>
? ? ? ? ? ? ? ? <value>classpath:/jdbc.properties</value>
? ? ? ? ? ? </list>
? ? ? ? </property>
? ? ? ? <property name="fileEncoding" value="utf-8"/>
? ? </bean>
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer">
? ? <property name="properties" ref="configProperties" />
</bean>
<!-- 使用proxool連接池的數(shù)據(jù)源, -->
<bean id="dataSource" class="org.logicalcobwebs.proxool.ProxoolDataSource">
? ? <!-- 數(shù)據(jù)源的別名 -->
? ? <property name="alias" value="${proxool.alias}" />?
? ? <!-- 驅(qū)動 -->
? ? <property name="driver" value="${proxool.driver}" />?
? ? <!-- 鏈接URL ?-->
? ? <property name="driverUrl" value="${proxool.driverUrl}" />?
? ? <!-- 用戶名-->
? ? <property name="user" value="${proxool.user}" />
? ? <!-- 密碼 -->
? ? <property name="password" value="${proxool.password}" />?
? ? <!-- 最大鏈接數(shù)-->
? ? <property name="maximumConnectionCount" value="${proxool.maximumConnectionCount}" />?
? ? <!-- 最小鏈接數(shù) -->
? ? <property name="minimumConnectionCount" value="${proxool.minimumConnectionCount}" />?
? ? <!-- ...(略) -->
</bean>?

jdbc.properties

proxool.alias=mySql
proxool.driver=com.mysql.jdbc.Driver
proxool.driverUrl=jdbc:mysql://localhost:3306/test?characterEncoding=utf8
proxool.user=root
proxool.password=root
proxool.maximumActiveTime=1200
proxool.maximumConnectionCount=50
#...

使用javaBean配置數(shù)據(jù)源

DataSourceConfiguration類是數(shù)據(jù)源的javaBean配置方式,@Configuratio注解當(dāng)前類,

spring啟動時會掃描被@Configuratio注解的類,注入當(dāng)前類中配置的方法bean;

當(dāng)然別忘了啟用注解掃描:

<context:annotation-config/> ?
<context:component-scan base-package="com.XXX.test.dateSource"></context:component-scan>

@value注解讀取配置

@value中可以直接使用SpEL,獲取properties配置,成員變量也不需要getter、setter,不過還是有一個前提,需要配置xml:

<bean id="configProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
? ? ? ? <property name="locations">
? ? ? ? ? ? <list>
? ? ? ? ? ? ? ? <value>classpath:/jdbc.properties</value>
? ? ? ? ? ? </list>
? ? ? ? </property>
? ? ? ? <property name="fileEncoding" value="utf-8"/>
? ? </bean>
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PreferencesPlaceholderConfigurer">
? ? <property name="properties" ref="configProperties" />
</bean>

@Bean注解:spring掃面當(dāng)前類時,注入每個有@Bean注解的方法的返回值Bean, name屬性默認(rèn)為返回值類類名首字母小寫,這里自己設(shè)置name。

package com.XXX.test.dateSource;
import org.logicalcobwebs.proxool.ProxoolDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuratio
public class DataSourceConfiguration{
? ? @Value("${proxool.alias}")
? ? private String alias;
? ? @Value("${proxool.driver}")
? ? private String driver;
? ? @Value("${proxool.driverUrl}")
? ? private String driverUrl;
? ? @Value("${proxool.user}")
? ? private String user;
? ? @Value("${proxool.password}")
? ? private String password;
? ? //...
? ? @Bean(name="dataSource")
? ? public ProxoolDataSource dataSource(){
? ? ? ? ?ProxoolDataSource proxoolDataSource = new ProxoolDataSource();
? ? ? ? ?proxoolDataSource.setDriver(driver);
? ? ? ? ?proxoolDataSource.setDriverUrl(driverUrl);
? ? ? ? ?proxoolDataSource.setUser(user);
? ? ? ? ?proxoolDataSource.setPassword(password);
? ? ? ? ?//...
? ? ? ? ?return proxoolDataSource;
? ? ?}
?}

這時dataSource已被注入,使用時可注解注入,如下:

? ? @Autowired
? ? private ProxoolDataSource dataSource;

@PropertySource注解讀取配置

@PropertySource注解當(dāng)前類,參數(shù)為對應(yīng)的配置文件路徑,這種方式加載配置文件,可不用在xml中配置PropertiesFactoryBean引入jdbc.properties,使用時方便得多,DataSourceConfiguration不再需要成員變量,取而代之的是需要注入一個Environment環(huán)境配置,使用env.getProperty(key)獲取數(shù)據(jù):

package com.XXX.test.dateSource;
import org.logicalcobwebs.proxool.ProxoolDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
@Configuratio
@PropertySource("classpath:/jdbc.properties")
public class DataSourceConfiguration{
? ? @Autowired
? ? private Environment env;
? ? @Bean(name="dataSource")
? ? public ProxoolDataSource dataSource(){
? ? ? ? ?ProxoolDataSource proxoolDataSource = new ProxoolDataSource();
? ? ? ? ?proxoolDataSource.setDriver(env.getProperty("proxool.alias"));
? ? ? ? ?proxoolDataSource.setDriverUrl(env.getProperty("proxool.driver"));
? ? ? ? ?proxoolDataSource.setUser(env.getProperty("proxool.user"));
? ? ? ? ?proxoolDataSource.setPassword(env.getProperty("proxool.password"));
? ? ? ? ?//...
? ? ? ? ?return proxoolDataSource;
? ? ?}
?}

這里主要是說明注解的用法,所以沒有具體體現(xiàn)數(shù)據(jù)源全部參數(shù)的配置。對于有強(qiáng)迫癥的來說若項目中所有bean都使用注解,幾乎不太希望僅dataSource用xml類配置,換成類的方式類配置強(qiáng)迫感就消失了! 

注解的spring多數(shù)據(jù)源配置及使用

前一段時間研究了一下spring多數(shù)據(jù)源的配置和使用,為了后期從多個數(shù)據(jù)源拉取數(shù)據(jù)定時進(jìn)行數(shù)據(jù)分析和報表統(tǒng)計做準(zhǔn)備。由于之前做過的項目都是單數(shù)據(jù)源的,沒有遇到這種場景,所以也一直沒有去了解過如何配置多數(shù)據(jù)源。

后來發(fā)現(xiàn)其實基于spring來配置和使用多數(shù)據(jù)源還是比較簡單的,因為spring框架已經(jīng)預(yù)留了這樣的接口可以方便數(shù)據(jù)源的切換。

先看一下spring獲取數(shù)據(jù)源的源碼

可以看到AbstractRoutingDataSource獲取數(shù)據(jù)源之前會先調(diào)用determineCurrentLookupKey方法查找當(dāng)前的lookupKey,這個lookupKey就是數(shù)據(jù)源標(biāo)識。

因此通過重寫這個查找數(shù)據(jù)源標(biāo)識的方法就可以讓spring切換到指定的數(shù)據(jù)源了。

第一步:創(chuàng)建一個DynamicDataSource的類

繼承AbstractRoutingDataSource并重寫determineCurrentLookupKey方法,代碼如下:

public class DynamicDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        // 從自定義的位置獲取數(shù)據(jù)源標(biāo)識
        return DynamicDataSourceHolder.getDataSource();
    }
}

第二步:創(chuàng)建DynamicDataSourceHolder

用于持有當(dāng)前線程中使用的數(shù)據(jù)源標(biāo)識,代碼如下:

public class DynamicDataSourceHolder {
    /**
     * 注意:數(shù)據(jù)源標(biāo)識保存在線程變量中,避免多線程操作數(shù)據(jù)源時互相干擾
     */
    private static final ThreadLocal<String> THREAD_DATA_SOURCE = new ThreadLocal<String>();
    public static String getDataSource() {
        return THREAD_DATA_SOURCE.get();
    }
    public static void setDataSource(String dataSource) {
        THREAD_DATA_SOURCE.set(dataSource);
    }
    public static void clearDataSource() {
        THREAD_DATA_SOURCE.remove();
    }
}

第三步:配置多個數(shù)據(jù)源

和第一步里創(chuàng)建的DynamicDataSource的bean,簡化的配置如下:

<!--創(chuàng)建數(shù)據(jù)源1,連接數(shù)據(jù)庫db1 -->
<bean id="dataSource1" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="${db1.driver}" />
    <property name="url" value="${db1.url}" />
    <property name="username" value="${db1.username}" />
    <property name="password" value="${db1.password}" />
</bean>
<!--創(chuàng)建數(shù)據(jù)源2,連接數(shù)據(jù)庫db2 -->
<bean id="dataSource2" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="${db2.driver}" />
    <property name="url" value="${db2.url}" />
    <property name="username" value="${db2.username}" />
    <property name="password" value="${db2.password}" />
</bean>
<!--創(chuàng)建數(shù)據(jù)源3,連接數(shù)據(jù)庫db3 -->
<bean id="dataSource3" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="${db3.driver}" />
    <property name="url" value="${db3.url}" />
    <property name="username" value="${db3.username}" />
    <property name="password" value="${db3.password}" />
</bean>
<bean id="dynamicDataSource" class="com.test.context.datasource.DynamicDataSource">
    <property name="targetDataSources">
        <map key-type="java.lang.String">
            <!-- 指定lookupKey和與之對應(yīng)的數(shù)據(jù)源 -->
            <entry key="dataSource1" value-ref="dataSource1"></entry>
            <entry key="dataSource2" value-ref="dataSource2"></entry>
            <entry key="dataSource3 " value-ref="dataSource3"></entry>
        </map>
    </property>
    <!-- 這里可以指定默認(rèn)的數(shù)據(jù)源 -->
    <property name="defaultTargetDataSource" ref="dataSource1" />
</bean>

到這里已經(jīng)可以使用多數(shù)據(jù)源了,在操作數(shù)據(jù)庫之前只要DynamicDataSourceHolder.setDataSource("dataSource2")即可切換到數(shù)據(jù)源2并對數(shù)據(jù)庫db2進(jìn)行操作了。

示例代碼如下:

@Service
public class DataServiceImpl implements DataService {
    @Autowired
    private DataMapper dataMapper;
    @Override
    public List<Map<String, Object>> getList1() {
        // 沒有指定,則默認(rèn)使用數(shù)據(jù)源1
        return dataMapper.getList1();
    }
    @Override
    public List<Map<String, Object>> getList2() {
        // 指定切換到數(shù)據(jù)源2
        DynamicDataSourceHolder.setDataSource("dataSource2");
        return dataMapper.getList2();
    }
    @Override
    public List<Map<String, Object>> getList3() {
        // 指定切換到數(shù)據(jù)源3
        DynamicDataSourceHolder.setDataSource("dataSource3");
        return dataMapper.getList3();
    }
}

----------------------------華麗的分割線----------------------------

但是問題來了,如果每次切換數(shù)據(jù)源時都調(diào)用DynamicDataSourceHolder.setDataSource("xxx")就顯得十分繁瑣了,而且代碼量大了很容易會遺漏,后期維護(hù)起來也比較麻煩。能不能直接通過注解的方式指定需要訪問的數(shù)據(jù)源呢,比如在dao層使用@DataSource("xxx")就指定訪問數(shù)據(jù)源xxx?當(dāng)然可以!前提是,再加一點額外的配置^_^。

首先,我們得定義一個名為DataSource的注解,代碼如下:

@Target({ TYPE, METHOD })
@Retention(RUNTIME)
public @interface DataSource {
    String value();
}

然后,定義AOP切面以便攔截所有帶有注解@DataSource的方法,取出注解的值作為數(shù)據(jù)源標(biāo)識放到DynamicDataSourceHolder的線程變量中:

public class DataSourceAspect {
    /**
     * 攔截目標(biāo)方法,獲取由@DataSource指定的數(shù)據(jù)源標(biāo)識,設(shè)置到線程存儲中以便切換數(shù)據(jù)源
     *
     * @param point
     * @throws Exception
     */
    public void intercept(JoinPoint point) throws Exception {
        Class<?> target = point.getTarget().getClass();
        MethodSignature signature = (MethodSignature) point.getSignature();
        // 默認(rèn)使用目標(biāo)類型的注解,如果沒有則使用其實現(xiàn)接口的注解
        for (Class<?> clazz : target.getInterfaces()) {
            resolveDataSource(clazz, signature.getMethod());
        }
        resolveDataSource(target, signature.getMethod());
    }
    /**
     * 提取目標(biāo)對象方法注解和類型注解中的數(shù)據(jù)源標(biāo)識
     *
     * @param clazz
     * @param method
     */
    private void resolveDataSource(Class<?> clazz, Method method) {
        try {
            Class<?>[] types = method.getParameterTypes();
            // 默認(rèn)使用類型注解
            if (clazz.isAnnotationPresent(DataSource.class)) {
                DataSource source = clazz.getAnnotation(DataSource.class);
                DynamicDataSourceHolder.setDataSource(source.value());
            }
            // 方法注解可以覆蓋類型注解
            Method m = clazz.getMethod(method.getName(), types);
            if (m != null && m.isAnnotationPresent(DataSource.class)) {
                DataSource source = m.getAnnotation(DataSource.class);
                DynamicDataSourceHolder.setDataSource(source.value());
            }
        } catch (Exception e) {
            System.out.println(clazz + ":" + e.getMessage());
        }
    }
}

最后在spring配置文件中配置攔截規(guī)則就可以了,比如攔截service層或者dao層的所有方法:

<bean id="dataSourceAspect" class="com.test.context.datasource.DataSourceAspect" />
    <aop:config>
        <aop:aspect ref="dataSourceAspect">
            <!-- 攔截所有service方法 -->
            <aop:pointcut id="dataSourcePointcut" expression="execution(* com.test.*.dao.*.*(..))"/>
            <aop:before pointcut-ref="dataSourcePointcut" method="intercept" />
        </aop:aspect>
    </aop:config>
</bean>

OK,這樣就可以直接在類或者方法上使用注解@DataSource來指定數(shù)據(jù)源,不需要每次都手動設(shè)置了。

示例代碼如下:

@Service
// 默認(rèn)DataServiceImpl下的所有方法均訪問數(shù)據(jù)源1
@DataSource("dataSource1")
public class DataServiceImpl implements DataService {
    @Autowired
    private DataMapper dataMapper;
    @Override
    public List<Map<String, Object>> getList1() {
        // 不指定,則默認(rèn)使用數(shù)據(jù)源1
        return dataMapper.getList1();
    }
    @Override
    // 覆蓋類上指定的,使用數(shù)據(jù)源2
    @DataSource("dataSource2")
    public List<Map<String, Object>> getList2() {
        return dataMapper.getList2();
    }
    @Override
    // 覆蓋類上指定的,使用數(shù)據(jù)源3
    @DataSource("dataSource3")
    public List<Map<String, Object>> getList3() {
        return dataMapper.getList3();
    }
}

提示:注解@DataSource既可以加在方法上,也可以加在接口或者接口的實現(xiàn)類上,優(yōu)先級別:方法>實現(xiàn)類>接口。也就是說如果接口、接口實現(xiàn)類以及方法上分別加了@DataSource注解來指定數(shù)據(jù)源,則優(yōu)先以方法上指定的為準(zhǔn)。

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

相關(guān)文章

  • Spring Security基于HttpRequest配置權(quán)限示例詳解

    Spring Security基于HttpRequest配置權(quán)限示例詳解

    這篇文章主要介紹了Spring Security基于HttpRequest配置權(quán)限示例詳解,我們在配置中配置的url被封裝成RequestMatcher,而hasRole被封裝成AuthorityAuthorizationManager,本文結(jié)合示例代碼講解的非常詳細(xì),需要的朋友可以參考下
    2024-03-03
  • Java多線程同步工具類CountDownLatch詳解

    Java多線程同步工具類CountDownLatch詳解

    這篇文章主要介紹了Java多線程同步工具類CountDownLatch詳解,CountDownLatch是一個多線程同步工具類,在多線程環(huán)境中它允許多個線程處于等待狀態(tài),直到前面的線程執(zhí)行結(jié)束
    2022-06-06
  • java synchronized的用法及原理詳解

    java synchronized的用法及原理詳解

    如果要保證并發(fā)情況下多線程共享數(shù)據(jù)的訪問安全,操作的原子性,就可以使用synchronized關(guān)鍵字。這篇文章主要介紹了java synchronized的用法及原理,需要的朋友可以借鑒一下
    2021-08-08
  • 如何使用spring?boot的程序主線程中異步訪問外部接口

    如何使用spring?boot的程序主線程中異步訪問外部接口

    CompletableFuture.supplyAsync提供了一種強(qiáng)大的工具,使您能夠以異步方式執(zhí)行操作,充分利用多核處理器和提高程序性能,同時保持代碼的清晰性和可維護(hù)性,本文給大家介紹使用spring?boot的程序主線程中異步訪問外部接口,感興趣的朋友一起看看吧
    2023-10-10
  • Java BigDecimal類用法詳解

    Java BigDecimal類用法詳解

    BigDecimal 由任意精度的整數(shù)非標(biāo)度值 和32 位的整數(shù)標(biāo)度 (scale) 組成。如果為零或正數(shù),則標(biāo)度是小數(shù)點后的位數(shù)。如果為負(fù)數(shù),則將該數(shù)的非標(biāo)度值乘以 10 的負(fù)scale 次冪。
    2016-06-06
  • Dwr3.0純注解(純Java Code配置)配置與應(yīng)用淺析三之后端反向調(diào)用前端

    Dwr3.0純注解(純Java Code配置)配置與應(yīng)用淺析三之后端反向調(diào)用前端

    Dwr是為人所熟知的前端框架,其異步推送功能是為人所津津樂道的,下來主要研究一下它的這個功能是怎么應(yīng)用的;
    2016-04-04
  • Java輸出通過InetAddress獲得的IP地址數(shù)組詳細(xì)解析

    Java輸出通過InetAddress獲得的IP地址數(shù)組詳細(xì)解析

    由于byte被認(rèn)為是unsigned byte,所以最高位的1將會被解釋為符號位,另外Java中存儲是按照補碼存儲,所以1000 0111會被認(rèn)為是補碼形式,轉(zhuǎn)換成原碼便是1111 0001,轉(zhuǎn)換成十進(jìn)制數(shù)便是-121
    2013-09-09
  • Netty4之如何實現(xiàn)HTTP請求、響應(yīng)

    Netty4之如何實現(xiàn)HTTP請求、響應(yīng)

    這篇文章主要介紹了Netty4之如何實現(xiàn)HTTP請求、響應(yīng)問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-04-04
  • Java中Object類常用的12個方法(小結(jié))

    Java中Object類常用的12個方法(小結(jié))

    Java 中的 Object 方法在面試中是一個非常高頻的點,本文主要介紹了Java中Object類常用的12個方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-12-12
  • JAVA實現(xiàn)Excel和PDF上下標(biāo)的操作代碼

    JAVA實現(xiàn)Excel和PDF上下標(biāo)的操作代碼

    這篇文章主要介紹了JAVA實現(xiàn)Excel和PDF上下標(biāo),本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-09-09

最新評論

民权县| 庄河市| 岳池县| 安西县| 绥棱县| 无极县| 铜川市| 梅州市| 定兴县| 安岳县| 顺昌县| 灵寿县| 古田县| 时尚| 那曲县| 含山县| 封开县| 阿克陶县| 宜城市| 泸西县| 山西省| 锡林浩特市| 兴海县| 新乡县| 长泰县| 古蔺县| 文昌市| 阳江市| 双牌县| 蒙城县| 鄂尔多斯市| 凤山市| 康马县| 基隆市| 卓资县| 扎囊县| 巴东县| 五寨县| 桑日县| 蕲春县| 伊通|