下面列出了怎么用org.springframework.boot.context.properties.bind.Bindable的API类实例代码及写法,或者点击链接到github查看源代码。
public static void main(String[] args) {
ConfigurableApplicationContext context = new SpringApplicationBuilder(BinderBootstrap.class)
.web(WebApplicationType.NONE) // 非 Web 应用
.properties("user.city.postCode=0731")
.run(args);
ConfigurableEnvironment environment = context.getEnvironment();
// 从 Environment 中获取 ConfigurationPropertySource 集合
Iterable<ConfigurationPropertySource> sources = ConfigurationPropertySources.get(environment);
// 构造 Binder 对象,并使用 ConfigurationPropertySource 集合作为配置源
Binder binder = new Binder(sources);
// 构造 ConfigurationPropertyName(Spring Boot 2.0 API)
ConfigurationPropertyName propertyName = ConfigurationPropertyName.of("user.city.post-code");
// 构造 Bindable 对象,包装 postCode
Bindable<String> postCodeBindable = Bindable.of(String.class);
BindResult<String> result = binder.bind(propertyName, postCodeBindable);
String postCode = result.get();
System.out.println("postCode = " + postCode);
// 关闭上下文
context.close();
}
public BrpcConfig getServiceConfig(Class<?> serviceInterface) {
BrpcConfig brpcConfig = new BrpcConfig(global);
if (brpcConfig.getClient() == null) {
brpcConfig.setClient(new RpcClientConfig());
}
if (brpcConfig.getServer() == null) {
brpcConfig.setServer(new RpcServerConfig());
}
if (brpcConfig.getNaming() == null) {
brpcConfig.setNaming(new RpcNamingConfig());
}
String prefix = "brpc.custom." + normalizeName(serviceInterface.getName()) + ".";
Binder binder = Binder.get(environment);
binder.bind(prefix + "client", Bindable.ofInstance(brpcConfig.getClient()));
binder.bind(prefix + "server", Bindable.ofInstance(brpcConfig.getServer()));
binder.bind(prefix + "naming", Bindable.ofInstance(brpcConfig.getNaming()));
rewriteMap(brpcConfig.getNaming().getExtra());
return brpcConfig;
}
@Bean
public ApplicationRunner runner(DemoApplicationProperties myApplicationProperties, Environment environment) {
return args -> {
List<Address> addresses = Binder.get(environment)
.bind("demo.addresses", Bindable.listOf(Address.class))
.orElseThrow(IllegalStateException::new);
System.out.printf("Demo Addresses : %s\n", addresses);
// DEMO_ENV_1 Environment Variable
System.out.printf("Demo Env 1 : %s\n", environment.getProperty("demo.env[1]"));
System.out.printf("Demo First Name : %s\n", myApplicationProperties.getFirstName());
System.out.printf("Demo Last Name : %s\n", myApplicationProperties.getLastName());
System.out.printf("Demo Username : %s\n", myApplicationProperties.getUsername());
System.out.printf("Demo Working Time (Hours) : %s\n", myApplicationProperties.getWorkingTime().toHours());
System.out.printf("Demo Number : %d\n", myApplicationProperties.getNumber());
System.out.printf("Demo Telephone Number : %s\n", myApplicationProperties.getTelephoneNumber());
System.out.printf("Demo Email 1 : %s\n", myApplicationProperties.getEmailAddresses().get(0));
System.out.printf("Demo Email 2 : %s\n", myApplicationProperties.getEmailAddresses().get(1));
};
}
public static <T> T bind(ConfigurableEnvironment environment, @NonNull T properties) {
var configurationProperties = AnnotationUtils.findAnnotation(properties.getClass(), ConfigurationProperties.class);
if (configurationProperties == null) {
throw new IllegalArgumentException(properties.getClass() + " Must be annotated with @ConfigurationProperties");
}
var property = configurationProperties.prefix();
var validationBindHandler = new ValidationBindHandler(
new SpringValidatorAdapter(Validation.buildDefaultValidatorFactory().getValidator())
);
var bindable = Bindable.ofInstance(properties);
return Binder.get(environment).bind(property, bindable, validationBindHandler).orElseGet(bindable.getValue());
}
@Override
public void bind(Map<String, Object> configurationProperties, boolean ignoreUnknownFields,
boolean ignoreInvalidFields, Object configurationBean) {
Iterable<PropertySource<?>> propertySources = asList(new MapPropertySource("internal", configurationProperties));
// Converts ConfigurationPropertySources
Iterable<ConfigurationPropertySource> configurationPropertySources = from(propertySources);
// Wrap Bindable from DubboConfig instance
Bindable bindable = Bindable.ofInstance(configurationBean);
Binder binder = new Binder(configurationPropertySources, new PropertySourcesPlaceholdersResolver(propertySources));
// Get BindHandler
BindHandler bindHandler = getBindHandler(ignoreUnknownFields, ignoreInvalidFields);
// Bind
binder.bind("", bindable, bindHandler);
}
@Override
protected void doBind(Object bean, String beanName, String dataId, String groupId,
String configType, NacosConfigurationProperties properties, String content,
ConfigService configService) {
String name = "nacos-bootstrap-" + beanName;
NacosPropertySource propertySource = new NacosPropertySource(name, dataId,
groupId, content, configType);
environment.getPropertySources().addLast(propertySource);
Binder binder = Binder.get(environment);
ResolvableType type = getBeanType(bean, beanName);
Bindable<?> target = Bindable.of(type).withExistingValue(bean);
binder.bind(properties.prefix(), target);
publishBoundEvent(bean, beanName, dataId, groupId, properties, content,
configService);
publishMetadataEvent(bean, beanName, dataId, groupId, properties);
environment.getPropertySources().remove(name);
}
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context,
AnnotatedTypeMetadata metadata) {
String prefix = (String) attribute(metadata, "prefix");
Class<?> value = (Class<?>) attribute(metadata, "value");
ConfigurableEnvironment environment = (ConfigurableEnvironment) context.getEnvironment();
try {
new Binder(ConfigurationPropertySources.from(environment.getPropertySources()))
.bind(prefix, Bindable.of(value))
.orElseThrow(
() -> new FatalBeanException("Could not bind DataSourceSettings properties"));
return new ConditionOutcome(true, String.format("Map property [%s] is not empty", prefix));
} catch (Exception e) {
//ignore
}
return new ConditionOutcome(false, String.format("Map property [%s] is empty", prefix));
}
/**
* Binds the YAML formatted value of a deployment property to a {@link KubernetesDeployerProperties} instance.
*
* @param kubernetesDeployerProperties the map of Kubernetes deployer properties
* @param propertyKey the property key to obtain the value to bind for
* @param yamlLabel the label representing the field to bind to
* @return a {@link KubernetesDeployerProperties} with the bound property data
*/
private static KubernetesDeployerProperties bindProperties(Map<String, String> kubernetesDeployerProperties,
String propertyKey, String yamlLabel) {
String deploymentPropertyValue = kubernetesDeployerProperties.getOrDefault(propertyKey, "");
KubernetesDeployerProperties deployerProperties = new KubernetesDeployerProperties();
if (!StringUtils.isEmpty(deploymentPropertyValue)) {
try {
YamlPropertiesFactoryBean properties = new YamlPropertiesFactoryBean();
String tmpYaml = "{ " + yamlLabel + ": " + deploymentPropertyValue + " }";
properties.setResources(new ByteArrayResource(tmpYaml.getBytes()));
Properties yaml = properties.getObject();
MapConfigurationPropertySource source = new MapConfigurationPropertySource(yaml);
deployerProperties = new Binder(source)
.bind("", Bindable.of(KubernetesDeployerProperties.class)).get();
} catch (Exception e) {
throw new IllegalArgumentException(
String.format("Invalid binding property '%s'", deploymentPropertyValue), e);
}
}
return deployerProperties;
}
@Override
public BindHandler apply(BindHandler bindHandler) {
BindHandler handler = new AbstractBindHandler(bindHandler) {
@Override
public <T> Bindable<T> onStart(ConfigurationPropertyName name,
Bindable<T> target, BindContext context) {
final String configName = name.toString();
if (configName.contains("use") && configName.contains("native") &&
(configName.contains("encoding") || configName.contains("decoding"))) {
BindResult<T> result = context.getBinder().bind(name, target);
if (result.isBound()) {
if (configName.contains("encoding")) {
EncodingDecodingBindAdviceHandler.this.encodingSettingProvided = true;
}
else {
EncodingDecodingBindAdviceHandler.this.decodingSettingProvided = true;
}
return target.withExistingValue(result.get());
}
}
return bindHandler.onStart(name, target, context);
}
};
return handler;
}
static <T> T bindOrCreate(Bindable<T> bindable,
Map<String, Object> properties, String configurationPropertyName,
Validator validator, ConversionService conversionService) {
// see ConfigurationPropertiesBinder from spring boot for this definition.
BindHandler handler = new IgnoreTopLevelConverterNotFoundBindHandler();
if (validator != null) { // TODO: list of validators?
handler = new ValidationBindHandler(handler, validator);
}
List<ConfigurationPropertySource> propertySources = Collections
.singletonList(new MapConfigurationPropertySource(properties));
return new Binder(propertySources, null, conversionService)
.bindOrCreate(configurationPropertyName, bindable, handler);
}
public static JasyptEncryptorConfigurationProperties bindConfigProps(ConfigurableEnvironment environment) {
final BindHandler handler = new IgnoreErrorsBindHandler(BindHandler.DEFAULT);
final MutablePropertySources propertySources = environment.getPropertySources();
final Binder binder = new Binder(ConfigurationPropertySources.from(propertySources),
new PropertySourcesPlaceholdersResolver(propertySources),
ApplicationConversionService.getSharedInstance());
final JasyptEncryptorConfigurationProperties config = new JasyptEncryptorConfigurationProperties();
final ResolvableType type = ResolvableType.forClass(JasyptEncryptorConfigurationProperties.class);
final Annotation annotation = AnnotationUtils.findAnnotation(JasyptEncryptorConfigurationProperties.class,
ConfigurationProperties.class);
final Annotation[] annotations = new Annotation[]{annotation};
final Bindable<?> target = Bindable.of(type).withExistingValue(config).withAnnotations(annotations);
binder.bind("jasypt.encryptor", target, handler);
return config;
}
@Override
public void preInit(SpringProcessEngineConfiguration springProcessEngineConfiguration) {
GenericProperties genericProperties = camundaBpmProperties.getGenericProperties();
final Map<String, Object> properties = genericProperties.getProperties();
if (!CollectionUtils.isEmpty(properties)) {
ConfigurationPropertySource source = new MapConfigurationPropertySource(properties);
Binder binder = new Binder(source);
try {
if (genericProperties.isIgnoreUnknownFields()) {
binder.bind(ConfigurationPropertyName.EMPTY, Bindable.ofInstance(springProcessEngineConfiguration));
} else {
binder.bind(ConfigurationPropertyName.EMPTY, Bindable.ofInstance(springProcessEngineConfiguration), new NoUnboundElementsBindHandler(BindHandler.DEFAULT));
}
} catch (Exception e) {
throw LOG.exceptionDuringBinding(e.getMessage());
}
logger.debug("properties bound to configuration: {}", genericProperties);
}
}
@SuppressWarnings("unchecked")
private void bindToDefault(String binding) {
T extendedBindingPropertiesTarget = (T) BeanUtils
.instantiateClass(this.getExtendedPropertiesEntryClass());
Binder binder = new Binder(
ConfigurationPropertySources
.get(this.applicationContext.getEnvironment()),
new PropertySourcesPlaceholdersResolver(
this.applicationContext.getEnvironment()),
IntegrationUtils.getConversionService(
this.applicationContext.getBeanFactory()),
null);
binder.bind(this.getDefaultsPrefix(),
Bindable.ofInstance(extendedBindingPropertiesTarget));
this.bindings.put(binding, extendedBindingPropertiesTarget);
}
@Override
public BindHandler apply(BindHandler bindHandler) {
BindHandler handler = new AbstractBindHandler(bindHandler) {
@Override
public <T> Bindable<T> onStart(ConfigurationPropertyName name,
Bindable<T> target, BindContext context) {
ConfigurationPropertyName defaultName = getDefaultName(name);
if (defaultName != null) {
BindResult<T> result = context.getBinder().bind(defaultName, target);
if (result.isBound()) {
return target.withExistingValue(result.get());
}
}
return bindHandler.onStart(name, target, context);
}
};
return handler;
}
private void reinitializeLoggingSystem(ConfigurableEnvironment environment,
String oldLogConfig, LogFile oldLogFile) {
Map<String, Object> props = Binder.get(environment)
.bind("logging", Bindable.mapOf(String.class, Object.class))
.orElseGet(Collections::emptyMap);
if (!props.isEmpty()) {
String logConfig = environment.resolvePlaceholders("${logging.config:}");
LogFile logFile = LogFile.get(environment);
LoggingSystem system = LoggingSystem
.get(LoggingSystem.class.getClassLoader());
try {
ResourceUtils.getURL(logConfig).openStream().close();
// Three step initialization that accounts for the clean up of the logging
// context before initialization. Spring Boot doesn't initialize a logging
// system that hasn't had this sequence applied (since 1.4.1).
system.cleanUp();
system.beforeInitialize();
system.initialize(new LoggingInitializationContext(environment),
logConfig, logFile);
}
catch (Exception ex) {
PropertySourceBootstrapConfiguration.logger
.warn("Error opening logging config file " + logConfig, ex);
}
}
}
/**
* We are a bit inconsistent with how we configure service URLs, so we proceed in this order:
*
* <p>1) {@code spinnaker.extensibility.repositories.front50.url} 2) {@code front50.base-url} 3)
* {@code services.front50.base-url}
*
* @param environment The Spring environment
* @param front50RepositoryProps Front50 update repository configuration
* @return The configured Front50 URL
*/
private static URL getFront50Url(
Environment environment, PluginRepositoryProperties front50RepositoryProps) {
try {
return front50RepositoryProps.getUrl();
} catch (Exception e) {
log.warn(
"Front50 update repository URL is either not specified or malformed, falling back "
+ "to default configuration",
e);
return Binder.get(environment)
.bind("front50.base-url", Bindable.of(URL.class))
.orElseGet(
() ->
Binder.get(environment)
.bind("services.front50.base-url", Bindable.of(URL.class))
.get());
}
}
@Test
public void bind() {
String vcap = "{\"application_users\":[]," + "\"application_id\":\"9958288f-9842-4ddc-93dd-1ea3c90634cd\","
+ "\"instance_id\":\"bb7935245adf3e650dfb7c58a06e9ece\","
+ "\"instance_index\":0,\"version\":\"3464e092-1c13-462e-a47c-807c30318a50\","
+ "\"name\":\"foo\",\"uris\":[\"foo.cfapps.io\"]," + "\"started_at\":\"2013-05-29 02:37:59 +0000\","
+ "\"started_at_timestamp\":1369795079," + "\"host\":\"0.0.0.0\",\"port\":61034,"
+ "\"limits\":{\"mem\":128,\"disk\":1024,\"fds\":16384},"
+ "\"version\":\"3464e092-1c13-462e-a47c-807c30318a50\","
+ "\"name\":\"dsyerenv\",\"uris\":[\"dsyerenv.cfapps.io\"],"
+ "\"users\":[],\"start\":\"2013-05-29 02:37:59 +0000\"," + "\"state_timestamp\":1369795079}";
MockEnvironment env = new MockEnvironment();
env.setProperty("VCAP_APPLICATION", vcap);
new CloudFoundryVcapEnvironmentPostProcessor().postProcessEnvironment(env, null);
CloudFoundryApplicationProperties cfProperties = Binder.get(env)
.bind("vcap.application", Bindable.of(CloudFoundryApplicationProperties.class)).get();
assertThat(cfProperties.getApplicationId()).isEqualTo("9958288f-9842-4ddc-93dd-1ea3c90634cd");
assertThat(cfProperties.getInstanceIndex()).isEqualTo("0");
}
@Override
public void preInit(SpringProcessEngineConfiguration springProcessEngineConfiguration) {
GenericProperties genericProperties = camundaBpmProperties.getGenericProperties();
final Map<String, Object> properties = genericProperties.getProperties();
if (!CollectionUtils.isEmpty(properties)) {
ConfigurationPropertySource source = new MapConfigurationPropertySource(properties);
Binder binder = new Binder(source);
try {
if (genericProperties.isIgnoreUnknownFields()) {
binder.bind(ConfigurationPropertyName.EMPTY, Bindable.ofInstance(springProcessEngineConfiguration));
} else {
binder.bind(ConfigurationPropertyName.EMPTY, Bindable.ofInstance(springProcessEngineConfiguration), new NoUnboundElementsBindHandler(BindHandler.DEFAULT));
}
} catch (Exception e) {
throw LOG.exceptionDuringBinding(e.getMessage());
}
logger.debug("properties bound to configuration: {}", genericProperties);
}
}
@Override
public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata annotatedTypeMetadata) {
Binder binder = Binder.get(context.getEnvironment());
Map<String, Object> sslProperties = binder.bind("camel.ssl.config", Bindable.mapOf(String.class, Object.class)).orElse(Collections.emptyMap());
ConditionMessage.Builder message = ConditionMessage.forCondition("camel.ssl.config");
if (sslProperties.size() > 0) {
return ConditionOutcome.match(message.because("enabled"));
}
return ConditionOutcome.noMatch(message.because("not enabled"));
}
@ConditionalOnProperty(prefix = "", value = "", havingValue = "", matchIfMissing = true)
@ConditionalOnMissingBean
@Bean
public LauncherInfoProperties launcherInfoProperties(Environment environment) {
Properties map = new Properties();
Binder.get(environment)
.bind("formula.launcher", Bindable.mapOf(String.class, String.class))
.orElseGet(Collections::emptyMap).forEach(map::put);
if (properties.getLauncher().mode == InfoPropertiesInfoContributor.Mode.SIMPLE) {
}
return new LauncherInfoProperties(map);
}
private HostInfo getFirstNonLoopbackHostInfo(ConfigurableEnvironment environment) {
InetUtilsProperties target = new InetUtilsProperties();
ConfigurationPropertySources.attach(environment);
Binder.get(environment).bind(InetUtilsProperties.PREFIX, Bindable.ofInstance(target));
try (InetUtils utils = new InetUtils(target)) {
return utils.findFirstNonLoopbackHostInfo();
}
}
public static void main(String[] args) {
// Fluent API 构建新 Bindable 对象(不变)
Bindable bindable = Bindable.of(int.class)
.withExistingValue(1)
.withAnnotations();
echo(bindable);
}
/**
* Bind the environment to the {@link SpringApplication}.
* @param environment the environment to bind
*/
protected void bindToSpringApplication(ConfigurableEnvironment environment) {
try {
Binder.get(environment).bind("spring.main", Bindable.ofInstance(this));
}
catch (Exception ex) {
throw new IllegalStateException("Cannot bind to SpringApplication", ex);
}
}
/**
* create a hikari data source
* @see org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration.Hikari#dataSource
*/
public HikariDataSource createDataSource() {
HikariDataSource dataSource = dataSourceProperties.initializeDataSourceBuilder().type(HikariDataSource.class).build();
if (StringUtils.hasText(dataSourceProperties.getName())) {
dataSource.setPoolName(dataSourceProperties.getName());
}
Bindable<?> target = Bindable.of(HikariDataSource.class).withExistingValue(dataSource);
this.binder.bind("spring.datasource.hikari", target);
return dataSource;
}
public static NacosConfigProperties buildNacosConfigProperties(
ConfigurableEnvironment environment) {
NacosConfigProperties nacosConfigProperties = new NacosConfigProperties();
Binder binder = Binder.get(environment);
ResolvableType type = ResolvableType.forClass(NacosConfigProperties.class);
Bindable<?> target = Bindable.of(type).withExistingValue(nacosConfigProperties);
binder.bind(NacosConfigConstants.PREFIX, target);
logger.info("nacosConfigProperties : {}", nacosConfigProperties);
return nacosConfigProperties;
}
/**
* 获取配置
*
* @param beanFactory beanFactory
* @param prefix 前缀
* @return
*/
public static MangoConfig getMangoConfig(DefaultListableBeanFactory beanFactory, String prefix) {
MangoConfig config = new MangoConfig();
Bindable<?> target = Bindable.ofInstance(config);
PropertySources propertySources = getPropertySources(beanFactory);
BindHandler bindHandler = getBindHandler();
BindResult configBindResult = getBinder(propertySources, beanFactory).bind(prefix, target, bindHandler);
return (MangoConfig) configBindResult.get();
}
protected XADataSource createXaDataSource() {
String className = dataSourceClassName();
Assert.state(StringUtils.hasLength(className), "No XA DataSource class name specified");
XADataSource dataSource = createXaDataSourceInstance(className);
Bindable<XADataSource> bindable = Bindable.ofInstance(dataSource);
bindXaProperties(bindable);
return dataSource;
}
private void bindXaProperties(Bindable<XADataSource> target) {
ConfigurationPropertySource source = new MapConfigurationPropertySource(
this.properties);
ConfigurationPropertyNameAliases aliases = new ConfigurationPropertyNameAliases();
aliases.addAliases("url", "jdbc-url");
aliases.addAliases("username", "user");
aliases.addAliases("portNumber", "port");
aliases.addAliases("serverName", "server");
aliases.addAliases("databaseName", "database");
Binder binder = new Binder(source.withAliases(aliases));
binder.bind(ConfigurationPropertyName.EMPTY, target);
}
/**
* Volume mount deployment properties are specified in YAML format:
* <p>
* <code>
* spring.cloud.deployer.kubernetes.volumeMounts=[{name: 'testhostpath', mountPath: '/test/hostPath'},
* {name: 'testpvc', mountPath: '/test/pvc'}, {name: 'testnfs', mountPath: '/test/nfs'}]
* </code>
* <p>
* Volume mounts can be specified as deployer properties as well as app deployment properties.
* Deployment properties override deployer properties.
*
* @param deploymentProperties the deployment properties from {@link AppDeploymentRequest}
* @return the configured volume mounts
*/
List<VolumeMount> getVolumeMounts(Map<String, String> deploymentProperties) {
List<VolumeMount> volumeMounts = new ArrayList<>();
String volumeMountDeploymentProperty = PropertyParserUtils.getDeploymentPropertyValue(deploymentProperties,
this.propertyPrefix + ".volumeMounts");
if (!StringUtils.isEmpty(volumeMountDeploymentProperty)) {
try {
YamlPropertiesFactoryBean properties = new YamlPropertiesFactoryBean();
String tmpYaml = "{ volume-mounts: " + volumeMountDeploymentProperty + " }";
properties.setResources(new ByteArrayResource(tmpYaml.getBytes()));
Properties yaml = properties.getObject();
MapConfigurationPropertySource source = new MapConfigurationPropertySource(yaml);
KubernetesDeployerProperties deployerProperties = new Binder(source)
.bind("", Bindable.of(KubernetesDeployerProperties.class)).get();
volumeMounts.addAll(deployerProperties.getVolumeMounts());
} catch (Exception e) {
throw new IllegalArgumentException(
String.format("Invalid volume mount '%s'", volumeMountDeploymentProperty), e);
}
}
// only add volume mounts that have not already been added, based on the volume mount's name
// i.e. allow provided deployment volume mounts to override deployer defined volume mounts
volumeMounts.addAll(this.properties.getVolumeMounts().stream().filter(volumeMount -> volumeMounts.stream()
.noneMatch(existingVolumeMount -> existingVolumeMount.getName().equals(volumeMount.getName())))
.collect(Collectors.toList()));
return volumeMounts;
}
private KubernetesDeployerProperties bindDeployerProperties() throws Exception {
YamlPropertiesFactoryBean properties = new YamlPropertiesFactoryBean();
properties.setResources(new ClassPathResource("dataflow-server.yml"),
new ClassPathResource("dataflow-server-tolerations.yml"),
new ClassPathResource("dataflow-server-secretKeyRef.yml"),
new ClassPathResource("dataflow-server-configMapKeyRef.yml"),
new ClassPathResource("dataflow-server-podsecuritycontext.yml"),
new ClassPathResource("dataflow-server-nodeAffinity.yml"),
new ClassPathResource("dataflow-server-podAffinity.yml"),
new ClassPathResource("dataflow-server-podAntiAffinity.yml"));
Properties yaml = properties.getObject();
MapConfigurationPropertySource source = new MapConfigurationPropertySource(yaml);
return new Binder(source).bind("", Bindable.of(KubernetesDeployerProperties.class)).get();
}