重构 multi-tenant library
diff --git a/multi-tenant-core/src/main/java/com/supwisdom/multitenant/HttpHeaderAutoRegistrar.java b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/HttpHeaderAutoRegistrar.java
new file mode 100644
index 0000000..c18c009
--- /dev/null
+++ b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/HttpHeaderAutoRegistrar.java
@@ -0,0 +1,33 @@
+package com.supwisdom.multitenant;
+
+import com.supwisdom.multitenant.config.HttpHeaderWebMvcConfig;
+import com.supwisdom.multitenant.impl.HttpHeaderTenantInterceptor;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+import org.springframework.beans.factory.support.GenericBeanDefinition;
+import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
+import org.springframework.core.type.AnnotationMetadata;
+
+public class HttpHeaderAutoRegistrar implements ImportBeanDefinitionRegistrar {
+  public static final String BEAN_NAME = "httpHeaderTenantInterceptor";
+
+  private void registerInterceptor(BeanDefinitionRegistry registry) {
+    GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
+    beanDefinition.setBeanClass(HttpHeaderTenantInterceptor.class);
+    beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
+    registry.registerBeanDefinition(BEAN_NAME, beanDefinition);
+  }
+
+  private void registerMvcConfigure(BeanDefinitionRegistry registry) {
+    GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
+    beanDefinition.setBeanClass(HttpHeaderWebMvcConfig.class);
+    beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
+    registry.registerBeanDefinition(BEAN_NAME + "MvcConfig", beanDefinition);
+  }
+
+  @Override
+  public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
+    registerInterceptor(registry);
+    registerMvcConfigure(registry);
+  }
+}
diff --git a/multi-tenant-core/src/main/java/com/supwisdom/multitenant/HttpSessionAutoRegistrar.java b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/HttpSessionAutoRegistrar.java
new file mode 100644
index 0000000..4064aea
--- /dev/null
+++ b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/HttpSessionAutoRegistrar.java
@@ -0,0 +1,33 @@
+package com.supwisdom.multitenant;
+
+import com.supwisdom.multitenant.config.HttpSessionWebMvcConfig;
+import com.supwisdom.multitenant.impl.HttpSessionTenantInterceptor;
+import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+import org.springframework.beans.factory.support.GenericBeanDefinition;
+import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
+import org.springframework.core.type.AnnotationMetadata;
+
+public class HttpSessionAutoRegistrar implements ImportBeanDefinitionRegistrar {
+  public static final String BEAN_NAME = "httpSessionTenantInterceptor";
+
+  private void registerInterceptor(BeanDefinitionRegistry registry) {
+    GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
+    beanDefinition.setBeanClass(HttpSessionTenantInterceptor.class);
+    beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
+    registry.registerBeanDefinition(BEAN_NAME, beanDefinition);
+}
+
+  private void registerMvcConfigurater(BeanDefinitionRegistry registry) {
+    GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
+    beanDefinition.setBeanClass(HttpSessionWebMvcConfig.class);
+    beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
+    registry.registerBeanDefinition(BEAN_NAME + "MvcConfig", beanDefinition);
+  }
+
+  @Override
+  public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
+    registerInterceptor(registry);
+    registerMvcConfigurater(registry);
+  }
+}
diff --git a/multi-tenant-core/src/main/java/com/supwisdom/multitenant/MultiTenantAutoConfiguration.java b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/MultiTenantAutoConfiguration.java
index 3ea1eb1..6a13357 100644
--- a/multi-tenant-core/src/main/java/com/supwisdom/multitenant/MultiTenantAutoConfiguration.java
+++ b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/MultiTenantAutoConfiguration.java
@@ -1,31 +1,38 @@
 package com.supwisdom.multitenant;
 
 import org.springframework.beans.factory.config.BeanDefinition;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.ComponentScan;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.context.annotation.Role;
 
+@Configuration
+@ComponentScan(basePackages = {"com.supwisdom.multitenant"})
+@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
 public class MultiTenantAutoConfiguration {
 
-  @Configuration
-  @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
-  @ComponentScan(basePackages = {"com.supwisdom.multitenant"})
+  @Bean
+  @ConditionalOnMissingBean(TenantDetailsProvider.class)
+  public TenantDetailsProvider createDetailsProvider() {
+    return new TenantDetailsProvider() {
+    };
+  }
+
   public static class SessionTenantInterceptorAutoConfig {
   }
 
-  //  @ConditionalOnProperty(
+//  @ConditionalOnProperty(
 //      name = "multi-tenant.interceptor.httpsession.enabled",
 //      havingValue = "true")
 //  @Bean
 //  @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
-//  @ConditionalOnBean({SessionTenantInterceptorAutoConfig.class})
-//  public SessionTenantInterceptorAutoConfig createSessionInterceptor() {
+//  public SessionTenantInterceptorAutoConfig sessionTenantInterceptorAutoConfig() {
 //    return new SessionTenantInterceptorAutoConfig();
 //  }
 
-  @Configuration
-  @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
-  @ComponentScan(basePackages = {"com.supwisdom.multitenant"})
+
   public static class HttpHeaderTenantInterceptorAutoConfig {
   }
 
@@ -34,7 +41,7 @@
 //      name = "multi-tenant.interceptor.httpheader.enabled",
 //      havingValue = "true")
 //  @Role(BeanDefinition.ROLE_INFRASTRUCTURE)
-//  public HttpHeaderTenantInterceptorAutoConfig createHttpHeaderInterceptor() {
+//  public HttpHeaderTenantInterceptorAutoConfig httpHeaderTenantInterceptorAutoConfig() {
 //    return new HttpHeaderTenantInterceptorAutoConfig();
 //  }
 }
diff --git a/multi-tenant-core/src/main/java/com/supwisdom/multitenant/TenantDetailsProvider.java b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/TenantDetailsProvider.java
new file mode 100644
index 0000000..d8d9990
--- /dev/null
+++ b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/TenantDetailsProvider.java
@@ -0,0 +1,9 @@
+package com.supwisdom.multitenant;
+
+public interface TenantDetailsProvider {
+  default TenantDetails createDetailsById(String id) {
+    TenantDetails details = new TenantDetails();
+    details.setId(id);
+    return details;
+  }
+}
diff --git a/multi-tenant-core/src/main/java/com/supwisdom/multitenant/annotations/EnableHttpHeaderTenantInterceptor.java b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/annotations/EnableHttpHeaderTenantInterceptor.java
index 97f8625..daf9d4c 100644
--- a/multi-tenant-core/src/main/java/com/supwisdom/multitenant/annotations/EnableHttpHeaderTenantInterceptor.java
+++ b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/annotations/EnableHttpHeaderTenantInterceptor.java
@@ -1,5 +1,6 @@
 package com.supwisdom.multitenant.annotations;
 
+import com.supwisdom.multitenant.HttpHeaderAutoRegistrar;
 import com.supwisdom.multitenant.MultiTenantAutoConfiguration;
 import org.springframework.context.annotation.Import;
 
@@ -7,7 +8,7 @@
 
 @Target(ElementType.TYPE)
 @Retention(RetentionPolicy.RUNTIME)
-@Import(MultiTenantAutoConfiguration.HttpHeaderTenantInterceptorAutoConfig.class)
+@Import({MultiTenantAutoConfiguration.class, HttpHeaderAutoRegistrar.class})
 @Documented
 public @interface EnableHttpHeaderTenantInterceptor {
 }
diff --git a/multi-tenant-core/src/main/java/com/supwisdom/multitenant/annotations/EnableSessionTenantInterceptor.java b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/annotations/EnableSessionTenantInterceptor.java
index 885140b..347b58d 100644
--- a/multi-tenant-core/src/main/java/com/supwisdom/multitenant/annotations/EnableSessionTenantInterceptor.java
+++ b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/annotations/EnableSessionTenantInterceptor.java
@@ -1,5 +1,6 @@
 package com.supwisdom.multitenant.annotations;
 
+import com.supwisdom.multitenant.HttpSessionAutoRegistrar;
 import com.supwisdom.multitenant.MultiTenantAutoConfiguration;
 import org.springframework.context.annotation.Import;
 
@@ -7,7 +8,7 @@
 
 @Target(ElementType.TYPE)
 @Retention(RetentionPolicy.RUNTIME)
-@Import(MultiTenantAutoConfiguration.SessionTenantInterceptorAutoConfig.class)
+@Import({MultiTenantAutoConfiguration.class, HttpSessionAutoRegistrar.class})
 @Documented
 public @interface EnableSessionTenantInterceptor {
 }
diff --git a/multi-tenant-core/src/main/java/com/supwisdom/multitenant/condition/OnPgDatabase.java b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/condition/OnPgDatabase.java
new file mode 100644
index 0000000..c09439d
--- /dev/null
+++ b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/condition/OnPgDatabase.java
@@ -0,0 +1,15 @@
+package com.supwisdom.multitenant.condition;
+
+import org.springframework.context.annotation.Condition;
+import org.springframework.context.annotation.ConditionContext;
+import org.springframework.core.type.AnnotatedTypeMetadata;
+
+public class OnPgDatabase implements Condition {
+  private static final String DATABASE_PLATFORM = "spring.jpa.database-platform";
+
+  @Override
+  public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
+    String platform = context.getEnvironment().getProperty(DATABASE_PLATFORM, String.class);
+    return "postgresql".equals(platform);
+  }
+}
diff --git a/multi-tenant-core/src/main/java/com/supwisdom/multitenant/config/HttpHeaderWebMvcConfig.java b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/config/HttpHeaderWebMvcConfig.java
index b2d9585..0227a23 100644
--- a/multi-tenant-core/src/main/java/com/supwisdom/multitenant/config/HttpHeaderWebMvcConfig.java
+++ b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/config/HttpHeaderWebMvcConfig.java
@@ -2,13 +2,11 @@
 
 
 import com.supwisdom.multitenant.impl.HttpHeaderTenantInterceptor;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
-import org.springframework.context.annotation.Configuration;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
 import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
 import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 
-@Configuration
-@ConditionalOnBean(value = {HttpHeaderTenantInterceptor.class})
+@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
 public class HttpHeaderWebMvcConfig implements WebMvcConfigurer {
   private final HttpHeaderTenantInterceptor interceptor;
 
diff --git a/multi-tenant-core/src/main/java/com/supwisdom/multitenant/config/HttpSessionWebMvcConfig.java b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/config/HttpSessionWebMvcConfig.java
new file mode 100644
index 0000000..c4d8030
--- /dev/null
+++ b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/config/HttpSessionWebMvcConfig.java
@@ -0,0 +1,20 @@
+package com.supwisdom.multitenant.config;
+
+import com.supwisdom.multitenant.impl.HttpSessionTenantInterceptor;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+@ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.SERVLET)
+public class HttpSessionWebMvcConfig implements WebMvcConfigurer {
+  private final HttpSessionTenantInterceptor interceptor;
+
+  public HttpSessionWebMvcConfig(HttpSessionTenantInterceptor interceptor) {
+    this.interceptor = interceptor;
+  }
+
+  @Override
+  public void addInterceptors(InterceptorRegistry registry) {
+    registry.addInterceptor(interceptor);
+  }
+}
diff --git a/multi-tenant-core/src/main/java/com/supwisdom/multitenant/impl/HttpHeaderTenantInterceptor.java b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/impl/HttpHeaderTenantInterceptor.java
index b8ae342..375eda0 100644
--- a/multi-tenant-core/src/main/java/com/supwisdom/multitenant/impl/HttpHeaderTenantInterceptor.java
+++ b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/impl/HttpHeaderTenantInterceptor.java
@@ -1,18 +1,16 @@
 package com.supwisdom.multitenant.impl;
 
-import com.supwisdom.multitenant.*;
+import com.supwisdom.multitenant.TenantContextHolder;
+import com.supwisdom.multitenant.TenantDetails;
+import com.supwisdom.multitenant.TenantInterceptor;
 import com.supwisdom.multitenant.config.TenantHeaderProperties;
 import com.supwisdom.multitenant.config.TenantJwtProperties;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
-import org.springframework.stereotype.Component;
 import org.springframework.util.StringUtils;
 import org.springframework.web.servlet.ModelAndView;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-@Component
-@ConditionalOnBean(MultiTenantAutoConfiguration.HttpHeaderTenantInterceptorAutoConfig.class)
 public class HttpHeaderTenantInterceptor extends TenantInterceptor {
   private final TenantJwtProperties properties;
 
diff --git a/multi-tenant-core/src/main/java/com/supwisdom/multitenant/impl/HttpSessionTenantInterceptor.java b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/impl/HttpSessionTenantInterceptor.java
new file mode 100644
index 0000000..cb711e0
--- /dev/null
+++ b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/impl/HttpSessionTenantInterceptor.java
@@ -0,0 +1,45 @@
+package com.supwisdom.multitenant.impl;
+
+import com.supwisdom.multitenant.TenantContextHolder;
+import com.supwisdom.multitenant.TenantDetails;
+import com.supwisdom.multitenant.TenantDetailsProvider;
+import com.supwisdom.multitenant.TenantInterceptor;
+import com.supwisdom.multitenant.config.TenantSessionProperties;
+import org.springframework.web.servlet.ModelAndView;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+public class HttpSessionTenantInterceptor extends TenantInterceptor {
+  private final TenantSessionProperties properties;
+
+  private final TenantDetailsProvider provider;
+
+  public HttpSessionTenantInterceptor(TenantSessionProperties properties,
+                                      TenantDetailsProvider provider) {
+    this.properties = properties;
+    this.provider = provider;
+  }
+
+  @Override
+  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
+    Object details = request.getSession().getAttribute(properties.getName());
+    if (details != null) {
+      if (details instanceof TenantDetails) {
+        TenantContextHolder.getContext().setTenant((TenantDetails) details);
+      } else if (details instanceof String) {
+        TenantContextHolder.getContext().setTenant(provider.createDetailsById((String) details));
+      } else {
+        return false;
+      }
+    }
+    return super.preHandle(request, response, handler);
+  }
+
+  @Override
+  public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
+                         ModelAndView modelAndView) throws Exception {
+    TenantContextHolder.clearContext();
+    super.postHandle(request, response, handler, modelAndView);
+  }
+}
diff --git a/multi-tenant-core/src/main/java/com/supwisdom/multitenant/impl/SessionTenantInterceptor.java b/multi-tenant-core/src/main/java/com/supwisdom/multitenant/impl/SessionTenantInterceptor.java
deleted file mode 100644
index 3f9ae2c..0000000
--- a/multi-tenant-core/src/main/java/com/supwisdom/multitenant/impl/SessionTenantInterceptor.java
+++ /dev/null
@@ -1,39 +0,0 @@
-package com.supwisdom.multitenant.impl;
-
-import com.supwisdom.multitenant.*;
-import com.supwisdom.multitenant.config.TenantSessionProperties;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
-import org.springframework.stereotype.Component;
-import org.springframework.util.StringUtils;
-import org.springframework.web.servlet.ModelAndView;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-@Component
-@ConditionalOnBean(MultiTenantAutoConfiguration.SessionTenantInterceptorAutoConfig.class)
-public class SessionTenantInterceptor extends TenantInterceptor {
-  private final TenantSessionProperties properties;
-
-  public SessionTenantInterceptor(TenantSessionProperties properties) {
-    this.properties = properties;
-  }
-
-  @Override
-  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
-    String tenant = (String) request.getSession().getAttribute(properties.getName());
-    if (tenant != null && !StringUtils.isEmpty(tenant)) {
-      TenantDetails details = new TenantDetails();
-      details.setId(tenant);
-      TenantContextHolder.getContext().setTenant(details);
-    }
-    return super.preHandle(request, response, handler);
-  }
-
-  @Override
-  public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
-                         ModelAndView modelAndView) throws Exception {
-    TenantContextHolder.clearContext();
-    super.postHandle(request, response, handler, modelAndView);
-  }
-}
diff --git a/multi-tenant-core/src/test/java/com/supwisdom/multitenant/HttpHeaderTest.java b/multi-tenant-core/src/test/java/com/supwisdom/multitenant/HttpHeaderTest.java
new file mode 100644
index 0000000..ce1ce58
--- /dev/null
+++ b/multi-tenant-core/src/test/java/com/supwisdom/multitenant/HttpHeaderTest.java
@@ -0,0 +1,59 @@
+package com.supwisdom.multitenant;
+
+import com.supwisdom.multitenant.annotations.EnableHttpHeaderTenantInterceptor;
+import com.supwisdom.multitenant.condition.OnPgDatabase;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Conditional;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.context.TestPropertySource;
+
+import java.util.Arrays;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+
+@SpringBootTest(classes = {HttpHeaderTest.class})
+@TestPropertySource("/test.properties")
+@EnableHttpHeaderTenantInterceptor
+public class HttpHeaderTest {
+
+  @Autowired
+  private ApplicationContext appContext;
+
+  @Test
+  public void testSessionOk() {
+    assertThat(TenantContextHolder.getContext(), notNullValue());
+    assertThat(findBeanByName(HttpHeaderAutoRegistrar.BEAN_NAME), is(true));
+  }
+
+  @Test
+  public void testError() {
+    assertThat(findBeanByName(HttpSessionAutoRegistrar.BEAN_NAME), is(false));
+  }
+
+  @Configuration
+  static class PostgresTest {
+    @Bean
+    @Conditional(OnPgDatabase.class)
+    public PostgresTest testPg() {
+      return new PostgresTest();
+    }
+  }
+
+
+  private boolean findBeanByName(String name) {
+    String[] beans = appContext.getBeanDefinitionNames();
+    Arrays.sort(beans);
+    for (String bean : beans) {
+      if (name.equals(bean)) {
+        return true;
+      }
+    }
+    return false;
+  }
+}
diff --git a/multi-tenant-core/src/test/java/com/supwisdom/multitenant/AutoConfigurationTest.java b/multi-tenant-core/src/test/java/com/supwisdom/multitenant/HttpSessionTest.java
similarity index 66%
rename from multi-tenant-core/src/test/java/com/supwisdom/multitenant/AutoConfigurationTest.java
rename to multi-tenant-core/src/test/java/com/supwisdom/multitenant/HttpSessionTest.java
index 4286f3c..ea612e1 100644
--- a/multi-tenant-core/src/test/java/com/supwisdom/multitenant/AutoConfigurationTest.java
+++ b/multi-tenant-core/src/test/java/com/supwisdom/multitenant/HttpSessionTest.java
@@ -10,24 +10,36 @@
 import java.util.Arrays;
 
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
 import static org.hamcrest.Matchers.notNullValue;
 
-@SpringBootTest(classes = {AutoConfigurationTest.class})
-@EnableSessionTenantInterceptor
+@SpringBootTest(classes = {HttpSessionTest.class})
 @TestPropertySource("/test.properties")
-public class AutoConfigurationTest {
-
+@EnableSessionTenantInterceptor
+public class HttpSessionTest {
   @Autowired
   private ApplicationContext appContext;
 
   @Test
   public void testSessionOk() {
+    assertThat(TenantContextHolder.getContext(), notNullValue());
+    assertThat(findBeanByName(HttpSessionAutoRegistrar.BEAN_NAME), is(true));
+  }
+
+  @Test
+  public void testError() {
+    assertThat(findBeanByName(HttpHeaderAutoRegistrar.BEAN_NAME), is(false));
+  }
+
+
+  private boolean findBeanByName(String name) {
     String[] beans = appContext.getBeanDefinitionNames();
     Arrays.sort(beans);
     for (String bean : beans) {
-      System.out.println(bean);
+      if (name.equals(bean)) {
+        return true;
+      }
     }
-    assertThat(TenantContextHolder.getContext(), notNullValue());
+    return false;
   }
-
 }
diff --git a/multi-tenant-core/src/test/resources/test.properties b/multi-tenant-core/src/test/resources/test.properties
index 80c6377..d6cc728 100644
--- a/multi-tenant-core/src/test/resources/test.properties
+++ b/multi-tenant-core/src/test/resources/test.properties
@@ -1 +1,2 @@
-debug=true
\ No newline at end of file
+debug=true
+spring.jpa.database-platform=postgresql
diff --git a/multi-tenant-datasource/build.gradle b/multi-tenant-datasource/build.gradle
index 09ed014..bc2a812 100644
--- a/multi-tenant-datasource/build.gradle
+++ b/multi-tenant-datasource/build.gradle
@@ -17,7 +17,7 @@
 }
 
 dependencies {
-    implementation(":multi-tenant-core")
+    implementation project(":multi-tenant-core")
     implementation "org.springframework.boot:spring-boot-autoconfigure"
     implementation "commons-beanutils:commons-beanutils:${beanutilsVersion}"
     implementation "commons-codec:commons-codec:${codecVersion}"
diff --git a/multi-tenant-datasource/src/main/java/com/supwisdom/multitenant/datasource/MultiTenantConnectionProviderImpl.java b/multi-tenant-datasource/src/main/java/com/supwisdom/multitenant/datasource/MultiTenantConnectionProviderImpl.java
new file mode 100644
index 0000000..737cba0
--- /dev/null
+++ b/multi-tenant-datasource/src/main/java/com/supwisdom/multitenant/datasource/MultiTenantConnectionProviderImpl.java
@@ -0,0 +1,79 @@
+package com.supwisdom.multitenant.datasource;
+
+import com.supwisdom.multitenant.TenantContextHolder;
+import com.supwisdom.multitenant.TenantDetails;
+import lombok.extern.slf4j.Slf4j;
+import org.hibernate.HibernateException;
+import org.hibernate.engine.jdbc.connections.spi.MultiTenantConnectionProvider;
+import org.springframework.stereotype.Component;
+
+import javax.sql.DataSource;
+import java.sql.Connection;
+import java.sql.SQLException;
+
+/**
+ * Created by shuwei on 2018/12/4.
+ */
+@Slf4j
+@Component
+public class MultiTenantConnectionProviderImpl implements MultiTenantConnectionProvider {
+  private final DataSource dataSource;
+
+  private final MultiTenantDataSourceProvider dsProvider;
+
+  public MultiTenantConnectionProviderImpl(DataSource dataSource,
+                                           MultiTenantDataSourceProvider provider) {
+    this.dataSource = dataSource;
+    this.dsProvider = provider;
+  }
+
+  @Override
+  public Connection getAnyConnection() throws SQLException {
+    return dataSource.getConnection();
+  }
+
+  @Override
+  public void releaseAnyConnection(Connection connection) throws SQLException {
+    connection.close();
+  }
+
+  @Override
+  public Connection getConnection(String ti) throws SQLException {
+    TenantDetails tenant = TenantContextHolder.getContext().getTenant();
+    final Connection connection = getAnyConnection();
+    try {
+      if (tenant != null) {
+        log.debug("postgresql set search path to  <" + tenant.getDbSchema() + ">");
+        connection.createStatement().execute(dsProvider.getTenantSQL(tenant));
+      } else {
+        log.debug("postgresql set search path to public");
+        connection.createStatement().execute(dsProvider.getDefaultSQL());
+      }
+    } catch (SQLException e) {
+      assert tenant != null;
+      throw new HibernateException("Problem setting schema to " + tenant.toString(), e);
+    }
+    return connection;
+  }
+
+  @Override
+  public void releaseConnection(String tenantIdentifier, Connection connection) throws SQLException {
+    connection.close();
+  }
+
+  @Override
+  public boolean supportsAggressiveRelease() {
+    return false;
+  }
+
+  @SuppressWarnings("rawtypes")
+  @Override
+  public boolean isUnwrappableAs(Class unwrapType) {
+    return false;
+  }
+
+  @Override
+  public <T> T unwrap(Class<T> unwrapType) {
+    return null;
+  }
+}
diff --git a/multi-tenant-datasource/src/main/java/com/supwisdom/multitenant/datasource/MultiTenantDataSourceProvider.java b/multi-tenant-datasource/src/main/java/com/supwisdom/multitenant/datasource/MultiTenantDataSourceProvider.java
new file mode 100644
index 0000000..394b743
--- /dev/null
+++ b/multi-tenant-datasource/src/main/java/com/supwisdom/multitenant/datasource/MultiTenantDataSourceProvider.java
@@ -0,0 +1,9 @@
+package com.supwisdom.multitenant.datasource;
+
+import com.supwisdom.multitenant.TenantDetails;
+
+public interface MultiTenantDataSourceProvider {
+  String getDefaultSQL();
+
+  String getTenantSQL(TenantDetails details);
+}
diff --git a/multi-tenant-datasource/src/main/java/com/supwisdom/multitenant/datasource/MultiTenantFactory.java b/multi-tenant-datasource/src/main/java/com/supwisdom/multitenant/datasource/MultiTenantFactory.java
new file mode 100644
index 0000000..6706bd1
--- /dev/null
+++ b/multi-tenant-datasource/src/main/java/com/supwisdom/multitenant/datasource/MultiTenantFactory.java
@@ -0,0 +1,7 @@
+package com.supwisdom.multitenant.datasource;
+
+import com.supwisdom.multitenant.datasource.beans.TenantProps;
+
+public interface MultiTenantFactory {
+  TenantProps createMultiTenant();
+}
diff --git a/multi-tenant-datasource/src/main/java/com/supwisdom/multitenant/datasource/beans/TenantProps.java b/multi-tenant-datasource/src/main/java/com/supwisdom/multitenant/datasource/beans/TenantProps.java
new file mode 100644
index 0000000..5e0b6da
--- /dev/null
+++ b/multi-tenant-datasource/src/main/java/com/supwisdom/multitenant/datasource/beans/TenantProps.java
@@ -0,0 +1,5 @@
+package com.supwisdom.multitenant.datasource.beans;
+
+public class TenantProps {
+  private String schema;
+}
diff --git a/multi-tenant-datasource/src/main/java/com/supwisdom/multitenant/datasource/config/MultiTenantDataSourceAutoConfiguration.java b/multi-tenant-datasource/src/main/java/com/supwisdom/multitenant/datasource/config/MultiTenantDataSourceAutoConfiguration.java
new file mode 100644
index 0000000..db0c5f7
--- /dev/null
+++ b/multi-tenant-datasource/src/main/java/com/supwisdom/multitenant/datasource/config/MultiTenantDataSourceAutoConfiguration.java
@@ -0,0 +1,22 @@
+package com.supwisdom.multitenant.datasource.config;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.beans.factory.support.BeanDefinitionRegistry;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
+import org.springframework.core.type.AnnotationMetadata;
+
+@Configuration
+public class MultiTenantDataSourceAutoConfiguration implements ImportBeanDefinitionRegistrar {
+
+  @Value("${spring.jpa.database-platform:all}")
+  private String datasourcePlatform;
+
+  @Override
+  public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
+//    GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
+//    beanDefinition.setBeanClass();
+//    registry.registerBeanDefinition();
+  }
+
+}
diff --git a/multi-tenant-datasource/src/main/java/com/supwisdom/payapi/multitenant/config/HibernateConfig.java b/multi-tenant-datasource/src/main/java/com/supwisdom/multitenant/datasource/config/MutliTenantHibernateConfig.java
similarity index 84%
rename from multi-tenant-datasource/src/main/java/com/supwisdom/payapi/multitenant/config/HibernateConfig.java
rename to multi-tenant-datasource/src/main/java/com/supwisdom/multitenant/datasource/config/MutliTenantHibernateConfig.java
index 3365265..87be5f6 100644
--- a/multi-tenant-datasource/src/main/java/com/supwisdom/payapi/multitenant/config/HibernateConfig.java
+++ b/multi-tenant-datasource/src/main/java/com/supwisdom/multitenant/datasource/config/MutliTenantHibernateConfig.java
@@ -1,12 +1,14 @@
-package com.supwisdom.payapi.multitenant.config;
+package com.supwisdom.multitenant.datasource.config;
 
 
+import com.supwisdom.multitenant.MultiTenantAutoConfiguration;
 import lombok.extern.slf4j.Slf4j;
 import org.hibernate.MultiTenancyStrategy;
 import org.hibernate.cfg.Environment;
 import org.hibernate.context.spi.CurrentTenantIdentifierResolver;
 import org.hibernate.engine.jdbc.connections.spi.MultiTenantConnectionProvider;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
 import org.springframework.boot.autoconfigure.orm.jpa.HibernateProperties;
 import org.springframework.boot.autoconfigure.orm.jpa.HibernateSettings;
 import org.springframework.boot.autoconfigure.orm.jpa.JpaProperties;
@@ -21,15 +23,16 @@
 import java.util.Map;
 
 @Configuration
+@ConditionalOnBean({MultiTenantAutoConfiguration.class})
 @Slf4j
-public class HibernateConfig {
+public class MutliTenantHibernateConfig {
 
   private final JpaProperties jpaProperties;
 
   private final HibernateProperties hibernateProperties;
 
-  public HibernateConfig(@Autowired JpaProperties jpaProperties,
-                         HibernateProperties hibernateProperties) {
+  public MutliTenantHibernateConfig(@Autowired JpaProperties jpaProperties,
+                                    HibernateProperties hibernateProperties) {
     this.jpaProperties = jpaProperties;
     this.hibernateProperties = hibernateProperties;
   }
diff --git a/multi-tenant-datasource/src/main/java/com/supwisdom/multitenant/datasource/impl/PostgresDataSourceProvider.java b/multi-tenant-datasource/src/main/java/com/supwisdom/multitenant/datasource/impl/PostgresDataSourceProvider.java
new file mode 100644
index 0000000..19305ef
--- /dev/null
+++ b/multi-tenant-datasource/src/main/java/com/supwisdom/multitenant/datasource/impl/PostgresDataSourceProvider.java
@@ -0,0 +1,25 @@
+package com.supwisdom.multitenant.datasource.impl;
+
+import com.supwisdom.multitenant.TenantDetails;
+import com.supwisdom.multitenant.datasource.MultiTenantDataSourceProvider;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.util.StringUtils;
+
+@Configuration
+@ConditionalOnExpression("${spring.jpa.database-platform:postgresql}")
+public class PostgresDataSourceProvider implements MultiTenantDataSourceProvider {
+  @Override
+  public String getTenantSQL(TenantDetails details) {
+    if (details == null || details.getDbSchema() == null
+        || StringUtils.isEmpty(details.getDbSchema())) {
+      return getDefaultSQL();
+    }
+    return String.format("set search_path \"%s\", public; ", details.getDbSchema());
+  }
+
+  @Override
+  public String getDefaultSQL() {
+    return "set search_path public;";
+  }
+}
diff --git a/multi-tenant-datasource/src/main/java/com/supwisdom/payapi/multitenant/DefaultMultiTenantFactory.java b/multi-tenant-datasource/src/main/java/com/supwisdom/payapi/multitenant/DefaultMultiTenantFactory.java
deleted file mode 100644
index 898e647..0000000
--- a/multi-tenant-datasource/src/main/java/com/supwisdom/payapi/multitenant/DefaultMultiTenantFactory.java
+++ /dev/null
@@ -1,4 +0,0 @@
-package com.supwisdom.payapi.multitenant;
-
-public class DefaultMultiTenantFactory implements MultiTenantFactory {
-}
diff --git a/multi-tenant-datasource/src/main/java/com/supwisdom/payapi/multitenant/MultiTenantFactory.java b/multi-tenant-datasource/src/main/java/com/supwisdom/payapi/multitenant/MultiTenantFactory.java
deleted file mode 100644
index 1c829f8..0000000
--- a/multi-tenant-datasource/src/main/java/com/supwisdom/payapi/multitenant/MultiTenantFactory.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.supwisdom.payapi.multitenant;
-
-public interface MultiTenantFactory {
-
-}
diff --git a/multi-tenant-datasource/src/main/java/com/supwisdom/payapi/multitenant/TenantContext.java b/multi-tenant-datasource/src/main/java/com/supwisdom/payapi/multitenant/TenantContext.java
deleted file mode 100644
index 4236e29..0000000
--- a/multi-tenant-datasource/src/main/java/com/supwisdom/payapi/multitenant/TenantContext.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.supwisdom.payapi.multitenant;
-
-import com.supwisdom.payapi.multitenant.beans.TenantProps;
-
-public class TenantContext {
-  private static final ThreadLocal<TenantProps> tenantHolder = new ThreadLocal<>();
-
-  public static TenantProps getTenant() {
-    return tenantHolder.get();
-  }
-
-  public static void setTenant(String tenant) {
-
-  }
-}
diff --git a/multi-tenant-datasource/src/main/java/com/supwisdom/payapi/multitenant/beans/TenantProps.java b/multi-tenant-datasource/src/main/java/com/supwisdom/payapi/multitenant/beans/TenantProps.java
deleted file mode 100644
index 6e0abf8..0000000
--- a/multi-tenant-datasource/src/main/java/com/supwisdom/payapi/multitenant/beans/TenantProps.java
+++ /dev/null
@@ -1,4 +0,0 @@
-package com.supwisdom.payapi.multitenant.beans;
-
-public class TenantProps {
-}
diff --git a/multi-tenant-datasource/src/main/java/com/supwisdom/payapi/multitenant/config/MultiTenantAutoConfiguration.java b/multi-tenant-datasource/src/main/java/com/supwisdom/payapi/multitenant/config/MultiTenantAutoConfiguration.java
deleted file mode 100644
index 718d869..0000000
--- a/multi-tenant-datasource/src/main/java/com/supwisdom/payapi/multitenant/config/MultiTenantAutoConfiguration.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.supwisdom.payapi.multitenant.config;
-
-import com.supwisdom.payapi.multitenant.DefaultMultiTenantFactory;
-import com.supwisdom.payapi.multitenant.MultiTenantFactory;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-@Configuration
-public class MultiTenantAutoConfiguration {
-  @Bean
-  @ConditionalOnMissingBean(MultiTenantFactory.class)
-  public MultiTenantFactory createFactory() {
-    return new DefaultMultiTenantFactory();
-  }
-}
diff --git a/multi-tenant-datasource/src/test/java/com/supwisdom/multitenant/datasource/PgDatasourceTest.java b/multi-tenant-datasource/src/test/java/com/supwisdom/multitenant/datasource/PgDatasourceTest.java
new file mode 100644
index 0000000..7aae07a
--- /dev/null
+++ b/multi-tenant-datasource/src/test/java/com/supwisdom/multitenant/datasource/PgDatasourceTest.java
@@ -0,0 +1,17 @@
+package com.supwisdom.multitenant.datasource;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.TestPropertySource;
+
+@SpringBootTest(classes = {PgDatasourceTest.class},
+    properties = {"multi-tenant.interceptor.httpsession.enabled=true",
+        "multi-tenant.interceptor.httpheader.enabled=true"})
+@TestPropertySource("/test-pg.properties")
+public class PgDatasourceTest {
+
+  @Test
+  public void connectDatasource() {
+
+  }
+}
diff --git a/multi-tenant-datasource/src/test/resources/test-pg.properties b/multi-tenant-datasource/src/test/resources/test-pg.properties
new file mode 100644
index 0000000..3613c3b
--- /dev/null
+++ b/multi-tenant-datasource/src/test/resources/test-pg.properties
@@ -0,0 +1,13 @@
+spring.main.banner-mode=off
+# create and drop tables and sequences, loads import.sql
+spring.jpa.hibernate.ddl-auto=update
+spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
+spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults=false
+# Postgresql settings
+spring.datasource.platform=postgresql
+#spring.datasource.url=jdbc:postgresql://ykt.supwisdom.com:15432/payapidev
+spring.datasource.url=jdbc:postgresql://172.28.201.70:15432/payapidev
+spring.datasource.username=payapi
+spring.datasource.password=123456
+spring.datasource.continue-on-error=true
+spring.datasource.initialization-mode=always
\ No newline at end of file