一、现象总结
运维人员只要一修改分布式配置,程序就报错,此时的健康检测也是出错。
但是,重启应用是能够成功的。
程序中有配置类使用注解@RefreshScope,用于实时更新,但又不想重启应用。
二、技术栈
分布式配置consul + spring boot 2.0 + mysql数据库连接池HicariCP
三、健康检测的错误详情
"status":"DOWN", "details":{ "diskSpace":{ "status":"UP", "details":{ "total":52710469632, "free":44208345088, "threshold":10485760 "db":{ "status":"UP", "details":{ "database":"MySQL", "hello":1 "elasticsearch":{ "status":"UP", "details":{ "clusterName":"es-cluster", "numberOfNodes":3, "numberOfDataNodes":3, "activePrimaryShards":94, "activeShards":193, "relocatingShards":0, "initializingShards":0, "unassignedShards":0 "refreshScope":{ "status":"DOWN", "details":{ "error":"org.springframework.boot.context.properties.ConfigurationPropertiesBindException: Error creating bean with name 'dataSource': Could not bind properties to 'HikariDataSource' : prefix=spring.datasource.hikari, ignoreInvalidFields=false, ignoreUnknownFields=true; nested exception is org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'spring.datasource.hikari' to com.zaxxer.hikari.HikariDataSource" "discoveryComposite":{ "status":"UP", "details":{ "discoveryClient":{ "status":"UP", "details":{ "services":[ "user-service" "hystrix":{ "status":"UP" "redis":{ "status":"UP", "details":{ "version":"3.2.11"四、java后端的日志打印出错详情
2021-03-04 10:51:01.651 ERROR 20017 --- [TaskScheduler-1] o.s.s.s.TaskUtils$LoggingErrorHandler : Unexpected error occurred in scheduled task.
org.springframework.boot.context.properties.ConfigurationPropertiesBindException: Error creating bean with name 'dataSource': Could not bind properties to 'HikariDataSource' : prefix=spring.datasource.hikari, ignoreInvalidFields=false, ignoreUnknownFields=true; nested exception is org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'spring.datasource.hikari' to com.zaxxer.hikari.HikariDataSource
at org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.bind(ConfigurationPropertiesBindingPostProcessor.java:109) ~[spring-boot-2.0.0.RELEASE.jar!/:2.0.0.RELEASE]
at org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.postProcessBeforeInitialization(ConfigurationPropertiesBindingPostProcessor.java:93) ~[spring-boot-2.0.0.RELEASE.jar!/:2.0.0.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:423) ~[spring-beans-5.0.4.RELEASE.jar!/:5.0.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1702) ~[spring-beans-5.0.4.RELEASE.jar!/:5.0.4.RELEASE]
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:414) ~[spring-beans-5.0.4.RELEASE.jar!/:5.0.4.RELEASE]
at org.springframework.cloud.context.properties.ConfigurationPropertiesRebinder.rebind(ConfigurationPropertiesRebinder.java:102) ~[spring-cloud-context-2.0.0.RELEASE.jar!/:2.0.0.RELEASE]
at org.springframework.cloud.context.properties.ConfigurationPropertiesRebinder.rebind(ConfigurationPropertiesRebinder.java:84) ~[spring-cloud-context-2.0.0.RELEASE.jar!/:2.0.0.RELEASE]
at org.springframework.cloud.context.properties.ConfigurationPropertiesRebinder.onApplicationEvent(ConfigurationPropertiesRebinder.java:141) ~[spring-cloud-context-2.0.0.RELEASE.jar!/:2.0.0.RELEASE]
at org.springframework.cloud.context.properties.ConfigurationPropertiesRebinder.onApplicationEvent(ConfigurationPropertiesRebinder.java:50) ~[spring-cloud-context-2.0.0.RELEASE.jar!/:2.0.0.RELEASE]
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172) ~[spring-context-5.0.4.RELEASE.jar!/:5.0.4.RELEASE]
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165) ~[spring-context-5.0.4.RELEASE.jar!/:5.0.4.RELEASE]
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139) ~[spring-context-5.0.4.RELEASE.jar!/:5.0.4.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:399) ~[spring-context-5.0.4.RELEASE.jar!/:5.0.4.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:353) ~[spring-context-5.0.4.RELEASE.jar!/:5.0.4.RELEASE]
at org.springframework.cloud.context.refresh.ContextRefresher.refresh(ContextRefresher.java:65) ~[spring-cloud-context-2.0.0.RELEASE.jar!/:2.0.0.RELEASE]
at org.springframework.cloud.endpoint.event.RefreshEventListener.handle(RefreshEventListener.java:36) ~[spring-cloud-context-2.0.0.RELEASE.jar!/:2.0.0.RELEASE]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_181]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_181]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_181]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_181]
at org.springframework.context.event.ApplicationListenerMethodAdapter.doInvoke(ApplicationListenerMethodAdapter.java:264) ~[spring-context-5.0.4.RELEASE.jar!/:5.0.4.RELEASE]
at org.springframework.context.event.ApplicationListenerMethodAdapter.processEvent(ApplicationListenerMethodAdapter.java:182) ~[spring-context-5.0.4.RELEASE.jar!/:5.0.4.RELEASE]
at org.springframework.context.event.ApplicationListenerMethodAdapter.onApplicationEvent(ApplicationListenerMethodAdapter.java:144) ~[spring-context-5.0.4.RELEASE.jar!/:5.0.4.RELEASE]
at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:172) ~[spring-context-5.0.4.RELEASE.jar!/:5.0.4.RELEASE]
at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:165) ~[spring-context-5.0.4.RELEASE.jar!/:5.0.4.RELEASE]
at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:139) ~[spring-context-5.0.4.RELEASE.jar!/:5.0.4.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:399) ~[spring-context-5.0.4.RELEASE.jar!/:5.0.4.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:353) ~[spring-context-5.0.4.RELEASE.jar!/:5.0.4.RELEASE]
at org.springframework.cloud.consul.config.ConfigWatch.watchConfigKeyValues(ConfigWatch.java:158) ~[spring-cloud-consul-config-2.0.0.RELEASE.jar!/:2.0.0.RELEASE]
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) ~[spring-context-5.0.4.RELEASE.jar!/:5.0.4.RELEASE]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_181]
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308) [na:1.8.0_181]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180) [na:1.8.0_181]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294) [na:1.8.0_181]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_181]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_181]
at java.lang.Thread.run(Thread.java:748) [na:1.8.0_181]
Caused by: org.springframework.boot.context.properties.bind.BindException: Failed to bind properties under 'spring.datasource.hikari' to com.zaxxer.hikari.HikariDataSource
at org.springframework.boot.context.properties.bind.Binder.handleBindError(Binder.java:250) ~[spring-boot-2.0.0.RELEASE.jar!/:2.0.0.RELEASE]
at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:226) ~[spring-boot-2.0.0.RELEASE.jar!/:2.0.0.RELEASE]
at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:210) ~[spring-boot-2.0.0.RELEASE.jar!/:2.0.0.RELEASE]
at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:192) ~[spring-boot-2.0.0.RELEASE.jar!/:2.0.0.RELEASE]
at org.springframework.boot.context.properties.ConfigurationPropertiesBinder.bind(ConfigurationPropertiesBinder.java:78) ~[spring-boot-2.0.0.RELEASE.jar!/:2.0.0.RELEASE]
at org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor.bind(ConfigurationPropertiesBindingPostProcessor.java:106) ~[spring-boot-2.0.0.RELEASE.jar!/:2.0.0.RELEASE]
... 36 common frames omitted
Caused by: java.lang.IllegalStateException: Unable to set value for property pool-name
at org.springframework.boot.context.properties.bind.JavaBeanBinder$BeanProperty.setValue(JavaBeanBinder.java:322) ~[spring-boot-2.0.0.RELEASE.jar!/:2.0.0.RELEASE]
at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:78) ~[spring-boot-2.0.0.RELEASE.jar!/:2.0.0.RELEASE]
at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:61) ~[spring-boot-2.0.0.RELEASE.jar!/:2.0.0.RELEASE]
at org.springframework.boot.context.properties.bind.JavaBeanBinder.bind(JavaBeanBinder.java:53) ~[spring-boot-2.0.0.RELEASE.jar!/:2.0.0.RELEASE]
at org.springframework.boot.context.properties.bind.Binder.lambda$null$5(Binder.java:339) ~[spring-boot-2.0.0.RELEASE.jar!/:2.0.0.RELEASE]
at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) ~[na:1.8.0_181]
at java.util.ArrayList$ArrayListSpliterator.tryAdvance(ArrayList.java:1359) ~[na:1.8.0_181]
at java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:126) ~[na:1.8.0_181]
at java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:498) ~[na:1.8.0_181]
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:485) ~[na:1.8.0_181]
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:471) ~[na:1.8.0_181]
at java.util.stream.FindOps$FindOp.evaluateSequential(FindOps.java:152) ~[na:1.8.0_181]
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:1.8.0_181]
at java.util.stream.ReferencePipeline.findFirst(ReferencePipeline.java:464) ~[na:1.8.0_181]
at org.springframework.boot.context.properties.bind.Binder.lambda$bindBean$6(Binder.java:340) ~[spring-boot-2.0.0.RELEASE.jar!/:2.0.0.RELEASE]
at org.springframework.boot.context.properties.bind.Binder$Context.withIncreasedDepth(Binder.java:439) ~[spring-boot-2.0.0.RELEASE.jar!/:2.0.0.RELEASE]
at org.springframework.boot.context.properties.bind.Binder$Context.withBean(Binder.java:425) ~[spring-boot-2.0.0.RELEASE.jar!/:2.0.0.RELEASE]
at org.springframework.boot.context.properties.bind.Binder$Context.access$400(Binder.java:379) ~[spring-boot-2.0.0.RELEASE.jar!/:2.0.0.RELEASE]
at org.springframework.boot.context.properties.bind.Binder.bindBean(Binder.java:337) ~[spring-boot-2.0.0.RELEASE.jar!/:2.0.0.RELEASE]
at org.springframework.boot.context.properties.bind.Binder.bindObject(Binder.java:279) ~[spring-boot-2.0.0.RELEASE.jar!/:2.0.0.RELEASE]
at org.springframework.boot.context.properties.bind.Binder.bind(Binder.java:221) ~[spring-boot-2.0.0.RELEASE.jar!/:2.0.0.RELEASE]
... 40 common frames omitted
Caused by: java.lang.reflect.InvocationTargetException: null
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_181]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_181]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_181]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_181]
at org.springframework.boot.context.properties.bind.JavaBeanBinder$BeanProperty.setValue(JavaBeanBinder.java:319) ~[spring-boot-2.0.0.RELEASE.jar!/:2.0.0.RELEASE]
... 60 common frames omitted
Caused by: java.lang.IllegalStateException: The configuration of the pool is sealed once started. Use HikariConfigMXBean for runtime changes.
at com.zaxxer.hikari.HikariConfig.setPoolName(HikariConfig.java:861) ~[HikariCP-2.7.8.jar!/:na]
... 65 common frames omitted
可以看出,主要的错误在于末尾!! 这也是仅从健康检测的错误提示,无法看到出错在哪的原因。
java.lang.IllegalStateException: The configuration of the pool is sealed once started. Use HikariConfigMXBean for runtime changes.
at com.zaxxer.hikari.HikariConfig.setPoolName(HikariConfig.java:861) ~[HikariCP-2.7.8.jar!/:na]
五、consul的主要配置
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://mysql2.xx.net:3306/xxx?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8&zeroDateTimeBehavior=convertToNull
username: xxxx
password: xxxx
type: com.zaxxer.hikari.HikariDataSource
hikari:
minimum-idle: 10
maximum-pool-size: 150
auto-commit: true
idle-timeout: 600000
pool-name: DatebookHikariCP
max-lifetime: 1800000
connection-timeout: 30000
六、出错的原因
1、com.zaxxer.hikari.HikariConfig.setPoolName
public void setPoolName(String poolName)
checkIfSealed();
this.poolName = poolName;
//这里引入了一个重要的vovatile变量
private volatile boolean sealed;
private void checkIfSealed()
if (sealed) throw new IllegalStateException("The configuration of the pool is sealed once started. Use HikariConfigMXBean for runtime changes.");
void seal()
this.sealed = true;
在数据源初始化和连接建立的时候,调用seal()方法。
见类public class HikariConnectionProvider implements ConnectionProvider, Configurable, Stoppable
if (isClosed()) {
throw new SQLException("HikariDataSource " + this + " has been closed.");
// 如果fast连接池存在,则直接跳转至获取连接的方法内。
if (fastPathPool != null) {
return fastPathPool.getConnection();
// See http://en.wikipedia.org/wiki/Double-checked_locking#Usage_in_Java
HikariPool result = pool;
if (result == null) {
synchronized (this) {
result = pool;
if (result == null) {
validate();
LOGGER.info("{} - Starting...", getPoolName());
try {
pool = result = new HikariPool(this);
this.seal();
catch (PoolInitializationException pie) {
if (pie.getCause() instanceof SQLException) {
throw (SQLException) pie.getCause();
else {
throw pie;
LOGGER.info("{} - Start completed.", getPoolName());
return result.getConnection();
PS: getConnection()里的实现,也比较简单,附上源码:
代码行数不错,先是采用Semaphore信号量的同步机制,实时触发关闭连接,循环判断是否超时,由PoolEntry去创建连接代理。同时收集指标信息。
public Connection getConnection(final long hardTimeout) throws SQLException
suspendResumeLock.acquire();
final long startTime = currentTime();
try {
long timeout = hardTimeout;
PoolEntry poolEntry = connectionBag.borrow(timeout, MILLISECONDS);
if (poolEntry == null) {
break; // We timed out... break and throw exception
final long now = currentTime();
if (poolEntry.isMarkedEvicted() || (elapsedMillis(poolEntry.lastAccessed, now) > aliveBypassWindowMs && !isConnectionAlive(poolEntry.connection))) {
closeConnection(poolEntry, poolEntry.isMarkedEvicted() ? EVICTED_CONNECTION_MESSAGE : DEAD_CONNECTION_MESSAGE);
timeout = hardTimeout - elapsedMillis(startTime);
else {
metricsTracker.recordBorrowStats(poolEntry, startTime);
return poolEntry.createProxyConnection(leakTaskFactory.schedule(poolEntry), now);
} while (timeout > 0L);
metricsTracker.recordBorrowTimeoutStats(startTime);
throw createTimeoutException(startTime);
catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new SQLException(poolName + " - Interrupted during connection acquisition", e);
finally {
suspendResumeLock.release();
2、配置自动加载
分析到这里,我们需要解释的是,为什么没有加@RefreshScope注解的数据库配置项会重新加载?
关于更多有关配置热更新的可以参考网址http://www.scienjus.com/spring-cloud-refresh/
文章开头说了,程序中并没有手写对于HikariCP的配置项,而是简单的使用@RefreshScope注解。
怀疑是spring boot autoconfigure 在加载数据源的时候,有指定刷新类DataSourceProperties。
"sourceType": "org.springframework.boot.autoconfigure.jdbc.DataSourceProperties",
"name": "spring.datasource.type",
"description": "Fully qualified name of the connection pool implementation to use. By default, it\n is auto-detected from the classpath.",
"type": "java.lang.Class<? extends javax.sql.DataSource>"
检索spring.datasource.type,找到它的java配置类是DataSourceProperties。
@ConfigurationProperties(
prefix = "spring.datasource"
public class DataSourceProperties implements BeanClassLoaderAware, InitializingBean {
这里也没有直接写类DataSourceProperties的scope=refresh.
于是,断点跟踪spring-cloud-context-2.0.0.RELEASE.jar中的几个关键类:
org.springframework.cloud.autoconfigure.ConfigurationPropertiesRebinderAutoConfiguration
@Bean
@ConditionalOnMissingBean(search = SearchStrategy.CURRENT)
public ConfigurationPropertiesBeans configurationPropertiesBeans() {
// Since this is a BeanPostProcessor we have to be super careful not to
// cause a cascade of bean instantiation. Knowing the *name* of the beans we
// need is super optimal, but a little brittle (unfortunately we have no
// choice).
ConfigurationBeanFactoryMetadata metaData = this.context.getBean(
ConfigurationBeanFactoryMetadata.BEAN_NAME,
ConfigurationBeanFactoryMetadata.class);
ConfigurationPropertiesBeans beans = new ConfigurationPropertiesBeans();
beans.setBeanMetaDataStore(metaData);
return beans;
@Bean
@ConditionalOnMissingBean(search = SearchStrategy.CURRENT)
public ConfigurationPropertiesRebinder configurationPropertiesRebinder(
ConfigurationPropertiesBeans beans) {
ConfigurationPropertiesRebinder rebinder = new ConfigurationPropertiesRebinder(
beans);
return rebinder;
进一步看ConfigurationPropertiesBeans类的实现细节,
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
// 如果bean的scope不是refresh, 则返回。
// 而org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Hikari的scope切实地等于refresh
if (isRefreshScoped(beanName)) {
return bean;
ConfigurationProperties annotation = AnnotationUtils.findAnnotation(
bean.getClass(), ConfigurationProperties.class);
if (annotation != null) {
this.beans.put(beanName, bean);
else if (this.metaData != null) {
annotation = this.metaData.findFactoryAnnotation(beanName,
ConfigurationProperties.class);
if (annotation != null) {
this.beans.put(beanName, bean);
return bean;
private boolean isRefreshScoped(String beanName) {
if (this.refreshScope == null && !this.refreshScopeInitialized) {
this.refreshScopeInitialized = true;
for (String scope : this.beanFactory.getRegisteredScopeNames()) {
if (this.beanFactory.getRegisteredScope(scope) instanceof org.springframework.cloud.context.scope.refresh.RefreshScope) {
this.refreshScope = scope;
break;
if (beanName == null || this.refreshScope == null) {
return false;
return this.beanFactory.containsBeanDefinition(beanName)
&& this.refreshScope.equals(this.beanFactory.getBeanDefinition(beanName)
.getScope());
至于为什么org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration$Hikari它的scope=refresh。可以看类org.springframework.cloud.autoconfigure.RefreshAutoConfiguration
@Component
protected static class RefreshScopeBeanDefinitionEnhancer
implements BeanDefinitionRegistryPostProcessor {
* Class names for beans to post process into refresh scope. Useful when you don't
* control the bean definition (e.g. it came from auto-configuration).
private Set<String> refreshables = new HashSet<>(
Arrays.asList("com.zaxxer.hikari.HikariDataSource"));
private Environment environment;
public Set<String> getRefreshable() {
return this.refreshables;
public void setRefreshable(Set<String> refreshables) {
if (this.refreshables != refreshables) {
this.refreshables.clear();
this.refreshables.addAll(refreshables);
public void setExtraRefreshable(Set<String> refreshables) {
this.refreshables.addAll(refreshables);
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
throws BeansException {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
throws BeansException {
for (String name : registry.getBeanDefinitionNames()) {
BeanDefinition definition = registry.getBeanDefinition(name);
if (isApplicable(registry, name, definition)) {
BeanDefinitionHolder holder = new BeanDefinitionHolder(definition,
name);
BeanDefinitionHolder proxy = ScopedProxyUtils
.createScopedProxy(holder, registry, true);
definition.setScope("refresh");
registry.registerBeanDefinition(proxy.getBeanName(),
proxy.getBeanDefinition());
private boolean isApplicable(BeanDefinitionRegistry registry, String name,
BeanDefinition definition) {
String scope = definition.getScope();
if ("refresh".equals(scope)) {
// Already refresh scoped
return false;
String type = definition.getBeanClassName();
if (registry instanceof BeanFactory) {
Class<?> cls = ((BeanFactory) registry).getType(name);
if (cls != null) {
type = cls.getName();
if (type != null) {
if (this.environment == null && registry instanceof BeanFactory) {
this.environment = ((BeanFactory) registry)
.getBean(Environment.class);
if (this.environment == null) {
this.environment = new StandardEnvironment();
Binder.get(environment).bind("spring.cloud.refresh",
Bindable.ofInstance(this));
return this.refreshables.contains(type);
return false;