Skip to content

Instantly share code, notes, and snippets.

@chocotan
Created May 12, 2017 02:21
Show Gist options
  • Save chocotan/966f131101062021e0a34ec67e5deee2 to your computer and use it in GitHub Desktop.
Save chocotan/966f131101062021e0a34ec67e5deee2 to your computer and use it in GitHub Desktop.
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import org.springframework.beans.FatalBeanException;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.boot.bind.PropertiesConfigurationFactory;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.jdbc.datasource.SingleConnectionDataSource;
import org.springframework.validation.BindException;
@Configuration
public class DynamicDataSourcesConfiguration implements ImportBeanDefinitionRegistrar, EnvironmentAware {
private ConfigurableEnvironment environment;
private static Map<String, Object> defaultDsProperties = new HashMap<String, Object>() {
{
put("suppressClose", true);
put("username", "sa");
put("password", "");
put("driverClassName", "org.h2.Driver");
}
};
@Override
public void setEnvironment(Environment environment) {
this.environment = (ConfigurableEnvironment)environment;
}
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
DataSourceSettings settings = resolveSettings();
for (Entry<String, String> entry : settings.clientDataSources().entrySet()) {
createDsBean(registry, entry.getKey(), entry.getValue());
}
}
private void createDsBean(BeanDefinitionRegistry registry, String beanName, String jdbcUrl) {
GenericBeanDefinition beanDefinition = createBeanDefinition(SingleConnectionDataSource.class);
beanDefinition.getPropertyValues().addPropertyValues(defaultDsProperties).addPropertyValue("url", jdbcUrl);
registry.registerBeanDefinition(beanName, beanDefinition);
}
private GenericBeanDefinition createBeanDefinition(Class<?> beanClass) {
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(beanClass);
beanDefinition.setAutowireMode(GenericBeanDefinition.AUTOWIRE_NO);
return beanDefinition;
}
private DataSourceSettings resolveSettings() {
DataSourceSettings settings = new DataSourceSettings();
PropertiesConfigurationFactory<Object> factory = new PropertiesConfigurationFactory<Object>(settings);
factory.setTargetName("ds");
factory.setPropertySources(environment.getPropertySources());
factory.setConversionService(environment.getConversionService());
try {
factory.bindPropertiesToTarget();
}
catch (BindException ex) {
throw new FatalBeanException("Could not bind DataSourceSettings properties", ex);
}
return settings;
}
}
package io.loli.kan;
import org.springframework.beans.BeansException;
import org.springframework.beans.FatalBeanException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.boot.bind.PropertiesConfigurationFactory;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@Component
public class DataSourcesBeanFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor,
EnvironmentAware {
private ConfigurableEnvironment environment;
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
TestProperties testProperties = new TestProperties();
PropertiesConfigurationFactory<Object> factory = new PropertiesConfigurationFactory<>(testProperties);
factory.setPropertySources(environment.getPropertySources());
factory.setConversionService(environment.getConversionService());
try {
factory.bindPropertiesToTarget();
} catch (BindException ex) {
throw new FatalBeanException("Could not bind DataSourceSettings properties", ex);
}
// 从配置文件中读取
System.out.println(factory.getObjectType());
for (String customerKey : testProperties.getCustomerNames()) {
String beanName = customerKey;
BeanDefinitionBuilder definitionBuilder =
BeanDefinitionBuilder.genericBeanDefinition(TestBean.class);
definitionBuilder.addPropertyValue("name", customerKey);
registry.registerBeanDefinition(beanName, definitionBuilder.getBeanDefinition());
}
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// we actually only add new beans, but do not post process the existing definitions
}
private static List<String> parseCustomerKeys(String rawCustomerKeys) {
if (StringUtils.isEmpty(rawCustomerKeys)) {
throw new IllegalArgumentException("Property 'customerKeys' is undefined.");
}
return Collections.unmodifiableList(Arrays.asList(StringUtils.split(rawCustomerKeys, ",")));
}
@Override
public void setEnvironment(Environment environment) {
this.environment = (ConfigurableEnvironment) environment;
}
public static class TestProperties{
private List<String> customerNames;
public List<String> getCustomerNames() {
return customerNames;
}
public void setCustomerNames(List<String> customerNames) {
this.customerNames = customerNames;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment