¶Ô±ÈÐÂÎļþ |
| | |
| | | /* |
| | | * Copyright (c) 2018-2028, Chill Zhuang All rights reserved. |
| | | * |
| | | * Redistribution and use in source and binary forms, with or without |
| | | * modification, are permitted provided that the following conditions are met: |
| | | * |
| | | * Redistributions of source code must retain the above copyright notice, |
| | | * this list of conditions and the following disclaimer. |
| | | * Redistributions in binary form must reproduce the above copyright |
| | | * notice, this list of conditions and the following disclaimer in the |
| | | * documentation and/or other materials provided with the distribution. |
| | | * Neither the name of the dreamlu.net developer nor the names of its |
| | | * contributors may be used to endorse or promote products derived from |
| | | * this software without specific prior written permission. |
| | | * Author: Chill åºéª (smallchill@163.com) |
| | | */ |
| | | package org.springblade.core.tenant.config; |
| | | |
| | | import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure; |
| | | import com.baomidou.dynamic.datasource.DynamicRoutingDataSource; |
| | | import com.baomidou.dynamic.datasource.aop.DynamicDataSourceAnnotationAdvisor; |
| | | import com.baomidou.dynamic.datasource.creator.DruidDataSourceCreator; |
| | | import com.baomidou.dynamic.datasource.processor.DsHeaderProcessor; |
| | | import com.baomidou.dynamic.datasource.processor.DsProcessor; |
| | | import com.baomidou.dynamic.datasource.processor.DsSessionProcessor; |
| | | import com.baomidou.dynamic.datasource.processor.DsSpelExpressionProcessor; |
| | | import com.baomidou.dynamic.datasource.provider.DynamicDataSourceProvider; |
| | | import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty; |
| | | import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceAutoConfiguration; |
| | | import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceCreatorAutoConfiguration; |
| | | import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceProperties; |
| | | import lombok.AllArgsConstructor; |
| | | import lombok.RequiredArgsConstructor; |
| | | import org.springblade.core.tenant.dynamic.*; |
| | | import org.springframework.beans.factory.SmartInitializingSingleton; |
| | | import org.springframework.beans.factory.config.BeanDefinition; |
| | | import org.springframework.boot.autoconfigure.AutoConfiguration; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; |
| | | import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; |
| | | import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; |
| | | import org.springframework.boot.context.properties.EnableConfigurationProperties; |
| | | import org.springframework.context.annotation.Bean; |
| | | import org.springframework.context.annotation.Import; |
| | | import org.springframework.context.annotation.Primary; |
| | | import org.springframework.context.annotation.Role; |
| | | import org.springframework.core.annotation.Order; |
| | | import org.springframework.jdbc.core.JdbcTemplate; |
| | | |
| | | import javax.sql.DataSource; |
| | | |
| | | import static org.springblade.core.tenant.constant.TenantBaseConstant.TENANT_DYNAMIC_DATASOURCE_PROP; |
| | | import static org.springblade.core.tenant.constant.TenantBaseConstant.TENANT_DYNAMIC_GLOBAL_PROP; |
| | | |
| | | /** |
| | | * å¤ç§æ·æ°æ®æºé
置类 |
| | | * |
| | | * @author Chill |
| | | */ |
| | | @RequiredArgsConstructor |
| | | @EnableConfigurationProperties({DataSourceProperties.class, DynamicDataSourceProperties.class}) |
| | | @AutoConfiguration(before = {DruidDataSourceAutoConfigure.class, DynamicDataSourceAutoConfiguration.class}) |
| | | @Import(value = {DynamicDataSourceCreatorAutoConfiguration.class}) |
| | | @ConditionalOnProperty(value = TENANT_DYNAMIC_DATASOURCE_PROP, havingValue = "true") |
| | | public class TenantDataSourceConfiguration { |
| | | |
| | | @Bean |
| | | @Primary |
| | | public DynamicDataSourceProvider dynamicDataSourceProvider(DataSourceProperties dataSourceProperties, DynamicDataSourceProperties dynamicDataSourceProperties) { |
| | | String driverClassName = dataSourceProperties.getDriverClassName(); |
| | | String url = dataSourceProperties.getUrl(); |
| | | String username = dataSourceProperties.getUsername(); |
| | | String password = dataSourceProperties.getPassword(); |
| | | DataSourceProperty master = dynamicDataSourceProperties.getDatasource().get(dynamicDataSourceProperties.getPrimary()); |
| | | if (master != null) { |
| | | driverClassName = master.getDriverClassName(); |
| | | url = master.getUrl(); |
| | | username = master.getUsername(); |
| | | password = master.getPassword(); |
| | | } |
| | | return new TenantDataSourceJdbcProvider(dynamicDataSourceProperties, driverClassName, url, username, password); |
| | | } |
| | | |
| | | @Bean |
| | | @Primary |
| | | public DataSource dataSource(DynamicDataSourceProvider dynamicDataSourceProvider, DynamicDataSourceProperties dynamicDataSourceProperties) { |
| | | DynamicRoutingDataSource dataSource = new DynamicRoutingDataSource(); |
| | | dataSource.setPrimary(dynamicDataSourceProperties.getPrimary()); |
| | | dataSource.setStrict(dynamicDataSourceProperties.getStrict()); |
| | | dataSource.setStrategy(dynamicDataSourceProperties.getStrategy()); |
| | | dataSource.setProvider(dynamicDataSourceProvider); |
| | | dataSource.setP6spy(dynamicDataSourceProperties.getP6spy()); |
| | | dataSource.setSeata(dynamicDataSourceProperties.getSeata()); |
| | | return dataSource; |
| | | } |
| | | |
| | | @Bean |
| | | @ConditionalOnMissingBean |
| | | public TenantDataSourceAnnotationInterceptor tenantDataSourceAnnotationInterceptor(DsProcessor dsProcessor, DynamicDataSourceProperties dynamicDataSourceProperties) { |
| | | return new TenantDataSourceAnnotationInterceptor(dynamicDataSourceProperties.isAllowedPublicOnly(), dsProcessor); |
| | | } |
| | | |
| | | @Bean |
| | | @ConditionalOnMissingBean |
| | | @Role(value = BeanDefinition.ROLE_INFRASTRUCTURE) |
| | | public DynamicDataSourceAnnotationAdvisor dynamicDatasourceAnnotationAdvisor(TenantDataSourceAnnotationInterceptor tenantDataSourceAnnotationInterceptor, DynamicDataSourceProperties dynamicDataSourceProperties) { |
| | | DynamicDataSourceAnnotationAdvisor advisor = new DynamicDataSourceAnnotationAdvisor(tenantDataSourceAnnotationInterceptor); |
| | | advisor.setOrder(dynamicDataSourceProperties.getOrder()); |
| | | return advisor; |
| | | } |
| | | |
| | | @Bean |
| | | @ConditionalOnMissingBean |
| | | @ConditionalOnProperty(value = TENANT_DYNAMIC_GLOBAL_PROP, havingValue = "true") |
| | | public TenantDataSourceGlobalInterceptor tenantDataSourceGlobalInterceptor() { |
| | | return new TenantDataSourceGlobalInterceptor(); |
| | | } |
| | | |
| | | @Bean |
| | | @ConditionalOnMissingBean |
| | | @Role(value = BeanDefinition.ROLE_INFRASTRUCTURE) |
| | | @ConditionalOnProperty(value = TENANT_DYNAMIC_GLOBAL_PROP, havingValue = "true") |
| | | public TenantDataSourceGlobalAdvisor tenantDataSourceGlobalAdvisor(TenantDataSourceGlobalInterceptor tenantDataSourceGlobalInterceptor, DynamicDataSourceProperties dynamicDataSourceProperties) { |
| | | TenantDataSourceGlobalAdvisor advisor = new TenantDataSourceGlobalAdvisor(tenantDataSourceGlobalInterceptor); |
| | | advisor.setOrder(dynamicDataSourceProperties.getOrder() + 1); |
| | | return advisor; |
| | | } |
| | | |
| | | @Bean |
| | | @ConditionalOnMissingBean |
| | | public DsProcessor dsProcessor() { |
| | | DsHeaderProcessor headerProcessor = new DsHeaderProcessor(); |
| | | DsSessionProcessor sessionProcessor = new DsSessionProcessor(); |
| | | DsTenantIdProcessor tenantIdProcessor = new DsTenantIdProcessor(); |
| | | DsSpelExpressionProcessor spelExpressionProcessor = new DsSpelExpressionProcessor(); |
| | | headerProcessor.setNextProcessor(sessionProcessor); |
| | | sessionProcessor.setNextProcessor(tenantIdProcessor); |
| | | tenantIdProcessor.setNextProcessor(spelExpressionProcessor); |
| | | return headerProcessor; |
| | | } |
| | | |
| | | @Order |
| | | @AutoConfiguration |
| | | @AllArgsConstructor |
| | | @ConditionalOnProperty(value = TENANT_DYNAMIC_DATASOURCE_PROP, havingValue = "true") |
| | | public static class TenantDataSourceAnnotationConfiguration implements SmartInitializingSingleton { |
| | | |
| | | private final TenantDataSourceAnnotationInterceptor tenantDataSourceAnnotationInterceptor; |
| | | |
| | | private final DataSource dataSource; |
| | | private final DruidDataSourceCreator dataSourceCreator; |
| | | private final JdbcTemplate jdbcTemplate; |
| | | |
| | | @Override |
| | | public void afterSingletonsInstantiated() { |
| | | TenantDataSourceHolder tenantDataSourceHolder = new TenantDataSourceHolder(dataSource, dataSourceCreator, jdbcTemplate); |
| | | tenantDataSourceAnnotationInterceptor.setHolder(tenantDataSourceHolder); |
| | | } |
| | | } |
| | | |
| | | @Order |
| | | @AutoConfiguration |
| | | @AllArgsConstructor |
| | | @ConditionalOnProperty(value = TENANT_DYNAMIC_GLOBAL_PROP, havingValue = "true") |
| | | public static class TenantDataSourceGlobalConfiguration implements SmartInitializingSingleton { |
| | | |
| | | private final TenantDataSourceGlobalInterceptor tenantDataSourceGlobalInterceptor; |
| | | |
| | | private final DataSource dataSource; |
| | | private final DruidDataSourceCreator dataSourceCreator; |
| | | private final JdbcTemplate jdbcTemplate; |
| | | |
| | | @Override |
| | | public void afterSingletonsInstantiated() { |
| | | TenantDataSourceHolder tenantDataSourceHolder = new TenantDataSourceHolder(dataSource, dataSourceCreator, jdbcTemplate); |
| | | tenantDataSourceGlobalInterceptor.setHolder(tenantDataSourceHolder); |
| | | } |
| | | } |
| | | |
| | | } |