Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
apollo
Project overview
Project overview
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
apollo
Commits
5823daa6
Unverified
Commit
5823daa6
authored
Feb 24, 2018
by
张乐
Committed by
GitHub
Feb 24, 2018
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #972 from nobodyiam/auto-update-value-merge
Auto Updating Spring Placeholder Values
parents
7edfb1aa
3efd4a33
Changes
42
Hide whitespace changes
Inline
Side-by-side
Showing
42 changed files
with
2841 additions
and
166 deletions
+2841
-166
apollo-client/src/main/java/com/ctrip/framework/apollo/internals/DefaultInjector.java
...com/ctrip/framework/apollo/internals/DefaultInjector.java
+4
-0
apollo-client/src/main/java/com/ctrip/framework/apollo/spring/annotation/ApolloConfigRegistrar.java
...ework/apollo/spring/annotation/ApolloConfigRegistrar.java
+4
-0
apollo-client/src/main/java/com/ctrip/framework/apollo/spring/annotation/SpringValueProcessor.java
...mework/apollo/spring/annotation/SpringValueProcessor.java
+317
-0
apollo-client/src/main/java/com/ctrip/framework/apollo/spring/boot/ApolloSpringApplicationRunListener.java
...pollo/spring/boot/ApolloSpringApplicationRunListener.java
+6
-1
apollo-client/src/main/java/com/ctrip/framework/apollo/spring/config/ConfigPropertySource.java
.../framework/apollo/spring/config/ConfigPropertySource.java
+6
-1
apollo-client/src/main/java/com/ctrip/framework/apollo/spring/config/ConfigPropertySourceFactory.java
...ork/apollo/spring/config/ConfigPropertySourceFactory.java
+23
-0
apollo-client/src/main/java/com/ctrip/framework/apollo/spring/config/ConfigPropertySourcesProcessor.java
.../apollo/spring/config/ConfigPropertySourcesProcessor.java
+16
-0
apollo-client/src/main/java/com/ctrip/framework/apollo/spring/config/PropertySourcesProcessor.java
...mework/apollo/spring/config/PropertySourcesProcessor.java
+4
-1
apollo-client/src/main/java/com/ctrip/framework/apollo/spring/property/PlaceholderHelper.java
...p/framework/apollo/spring/property/PlaceholderHelper.java
+127
-0
apollo-client/src/main/java/com/ctrip/framework/apollo/spring/property/SpringValue.java
...m/ctrip/framework/apollo/spring/property/SpringValue.java
+96
-0
apollo-client/src/main/java/com/ctrip/framework/apollo/spring/property/SpringValueDefinition.java
...amework/apollo/spring/property/SpringValueDefinition.java
+26
-0
apollo-client/src/main/java/com/ctrip/framework/apollo/spring/property/SpringValueDefinitionProcessor.java
...pollo/spring/property/SpringValueDefinitionProcessor.java
+96
-0
apollo-client/src/main/java/com/ctrip/framework/apollo/util/ConfigUtil.java
...main/java/com/ctrip/framework/apollo/util/ConfigUtil.java
+18
-0
apollo-client/src/test/java/com/ctrip/framework/apollo/AllTests.java
...nt/src/test/java/com/ctrip/framework/apollo/AllTests.java
+15
-10
apollo-client/src/test/java/com/ctrip/framework/apollo/build/MockInjector.java
...t/java/com/ctrip/framework/apollo/build/MockInjector.java
+0
-1
apollo-client/src/test/java/com/ctrip/framework/apollo/spring/AbstractSpringIntegrationTest.java
...ramework/apollo/spring/AbstractSpringIntegrationTest.java
+78
-1
apollo-client/src/test/java/com/ctrip/framework/apollo/spring/JavaConfigAnnotationTest.java
...rip/framework/apollo/spring/JavaConfigAnnotationTest.java
+2
-1
apollo-client/src/test/java/com/ctrip/framework/apollo/spring/JavaConfigPlaceholderAutoUpdateTest.java
...rk/apollo/spring/JavaConfigPlaceholderAutoUpdateTest.java
+1007
-0
apollo-client/src/test/java/com/ctrip/framework/apollo/spring/JavaConfigPlaceholderTest.java
...ip/framework/apollo/spring/JavaConfigPlaceholderTest.java
+53
-3
apollo-client/src/test/java/com/ctrip/framework/apollo/spring/XMLConfigAnnotationTest.java
...trip/framework/apollo/spring/XMLConfigAnnotationTest.java
+2
-1
apollo-client/src/test/java/com/ctrip/framework/apollo/spring/XmlConfigPlaceholderAutoUpdateTest.java
...ork/apollo/spring/XmlConfigPlaceholderAutoUpdateTest.java
+606
-0
apollo-client/src/test/java/com/ctrip/framework/apollo/spring/config/ConfigPropertySourceTest.java
...mework/apollo/spring/config/ConfigPropertySourceTest.java
+98
-0
apollo-client/src/test/java/com/ctrip/framework/apollo/spring/property/PlaceholderHelperTest.java
...amework/apollo/spring/property/PlaceholderHelperTest.java
+62
-0
apollo-client/src/test/java/com/ctrip/framework/apollo/util/ConfigUtilTest.java
.../java/com/ctrip/framework/apollo/util/ConfigUtilTest.java
+14
-2
apollo-client/src/test/resources/spring/XmlConfigPlaceholderTest10.xml
.../src/test/resources/spring/XmlConfigPlaceholderTest10.xml
+21
-0
apollo-client/src/test/resources/spring/XmlConfigPlaceholderTest7.xml
...t/src/test/resources/spring/XmlConfigPlaceholderTest7.xml
+13
-0
apollo-client/src/test/resources/spring/XmlConfigPlaceholderTest8.xml
...t/src/test/resources/spring/XmlConfigPlaceholderTest8.xml
+13
-0
apollo-client/src/test/resources/spring/XmlConfigPlaceholderTest9.xml
...t/src/test/resources/spring/XmlConfigPlaceholderTest9.xml
+16
-0
apollo-core/src/test/resources/META-INF/some-invalid-app.properties
...e/src/test/resources/META-INF/some-invalid-app.properties
+1
-1
apollo-demo/src/main/java/com/ctrip/framework/apollo/demo/api/ApolloConfigDemo.java
...com/ctrip/framework/apollo/demo/api/ApolloConfigDemo.java
+1
-1
apollo-demo/src/main/java/com/ctrip/framework/apollo/demo/spring/common/bean/AnnotatedBean.java
...amework/apollo/demo/spring/common/bean/AnnotatedBean.java
+6
-11
apollo-demo/src/main/java/com/ctrip/framework/apollo/demo/spring/common/config/AnotherAppConfig.java
...rk/apollo/demo/spring/common/config/AnotherAppConfig.java
+1
-1
apollo-demo/src/main/java/com/ctrip/framework/apollo/demo/spring/common/refresh/ApolloRefreshConfig.java
...pollo/demo/spring/common/refresh/ApolloRefreshConfig.java
+0
-37
apollo-demo/src/main/java/com/ctrip/framework/apollo/demo/spring/javaConfigDemo/AnnotationApplication.java
...llo/demo/spring/javaConfigDemo/AnnotationApplication.java
+20
-8
apollo-demo/src/main/java/com/ctrip/framework/apollo/demo/spring/javaConfigDemo/config/RefreshScopeConfig.java
...demo/spring/javaConfigDemo/config/RefreshScopeConfig.java
+0
-14
apollo-demo/src/main/java/com/ctrip/framework/apollo/demo/spring/springBootDemo/SpringBootSampleApplication.java
...mo/spring/springBootDemo/SpringBootSampleApplication.java
+24
-8
apollo-demo/src/main/java/com/ctrip/framework/apollo/demo/spring/springBootDemo/refresh/SpringBootApolloRefreshConfig.java
...springBootDemo/refresh/SpringBootApolloRefreshConfig.java
+15
-8
apollo-demo/src/main/java/com/ctrip/framework/apollo/demo/spring/xmlConfigDemo/XmlApplication.java
...work/apollo/demo/spring/xmlConfigDemo/XmlApplication.java
+21
-8
apollo-demo/src/main/java/com/ctrip/framework/apollo/demo/spring/xmlConfigDemo/bean/XmlBean.java
...mework/apollo/demo/spring/xmlConfigDemo/bean/XmlBean.java
+5
-0
apollo-demo/src/main/java/com/ctrip/framework/apollo/demo/spring/xmlConfigDemo/refresh/ManualRefreshUtil.java
.../demo/spring/xmlConfigDemo/refresh/ManualRefreshUtil.java
+0
-37
apollo-demo/src/main/resources/application.yml
apollo-demo/src/main/resources/application.yml
+2
-2
apollo-demo/src/main/resources/spring.xml
apollo-demo/src/main/resources/spring.xml
+2
-8
No files found.
apollo-client/src/main/java/com/ctrip/framework/apollo/internals/DefaultInjector.java
View file @
5823daa6
...
@@ -7,6 +7,8 @@ import com.ctrip.framework.apollo.spi.ConfigRegistry;
...
@@ -7,6 +7,8 @@ import com.ctrip.framework.apollo.spi.ConfigRegistry;
import
com.ctrip.framework.apollo.spi.DefaultConfigFactory
;
import
com.ctrip.framework.apollo.spi.DefaultConfigFactory
;
import
com.ctrip.framework.apollo.spi.DefaultConfigFactoryManager
;
import
com.ctrip.framework.apollo.spi.DefaultConfigFactoryManager
;
import
com.ctrip.framework.apollo.spi.DefaultConfigRegistry
;
import
com.ctrip.framework.apollo.spi.DefaultConfigRegistry
;
import
com.ctrip.framework.apollo.spring.config.ConfigPropertySourceFactory
;
import
com.ctrip.framework.apollo.spring.property.PlaceholderHelper
;
import
com.ctrip.framework.apollo.tracer.Tracer
;
import
com.ctrip.framework.apollo.tracer.Tracer
;
import
com.ctrip.framework.apollo.util.ConfigUtil
;
import
com.ctrip.framework.apollo.util.ConfigUtil
;
import
com.ctrip.framework.apollo.util.http.HttpUtil
;
import
com.ctrip.framework.apollo.util.http.HttpUtil
;
...
@@ -60,6 +62,8 @@ public class DefaultInjector implements Injector {
...
@@ -60,6 +62,8 @@ public class DefaultInjector implements Injector {
bind
(
HttpUtil
.
class
).
in
(
Singleton
.
class
);
bind
(
HttpUtil
.
class
).
in
(
Singleton
.
class
);
bind
(
ConfigServiceLocator
.
class
).
in
(
Singleton
.
class
);
bind
(
ConfigServiceLocator
.
class
).
in
(
Singleton
.
class
);
bind
(
RemoteConfigLongPollService
.
class
).
in
(
Singleton
.
class
);
bind
(
RemoteConfigLongPollService
.
class
).
in
(
Singleton
.
class
);
bind
(
PlaceholderHelper
.
class
).
in
(
Singleton
.
class
);
bind
(
ConfigPropertySourceFactory
.
class
).
in
(
Singleton
.
class
);
}
}
}
}
}
}
apollo-client/src/main/java/com/ctrip/framework/apollo/spring/annotation/ApolloConfigRegistrar.java
View file @
5823daa6
package
com
.
ctrip
.
framework
.
apollo
.
spring
.
annotation
;
package
com
.
ctrip
.
framework
.
apollo
.
spring
.
annotation
;
import
com.ctrip.framework.apollo.spring.property.SpringValueDefinitionProcessor
;
import
org.springframework.beans.factory.support.BeanDefinitionRegistry
;
import
org.springframework.beans.factory.support.BeanDefinitionRegistry
;
import
org.springframework.context.annotation.ImportBeanDefinitionRegistrar
;
import
org.springframework.context.annotation.ImportBeanDefinitionRegistrar
;
import
org.springframework.context.support.PropertySourcesPlaceholderConfigurer
;
import
org.springframework.context.support.PropertySourcesPlaceholderConfigurer
;
...
@@ -30,5 +31,8 @@ public class ApolloConfigRegistrar implements ImportBeanDefinitionRegistrar {
...
@@ -30,5 +31,8 @@ public class ApolloConfigRegistrar implements ImportBeanDefinitionRegistrar {
BeanRegistrationUtil
.
registerBeanDefinitionIfNotExists
(
registry
,
ApolloAnnotationProcessor
.
class
.
getName
(),
BeanRegistrationUtil
.
registerBeanDefinitionIfNotExists
(
registry
,
ApolloAnnotationProcessor
.
class
.
getName
(),
ApolloAnnotationProcessor
.
class
);
ApolloAnnotationProcessor
.
class
);
BeanRegistrationUtil
.
registerBeanDefinitionIfNotExists
(
registry
,
SpringValueProcessor
.
class
.
getName
(),
SpringValueProcessor
.
class
);
BeanRegistrationUtil
.
registerBeanDefinitionIfNotExists
(
registry
,
SpringValueDefinitionProcessor
.
class
.
getName
(),
SpringValueDefinitionProcessor
.
class
);
}
}
}
}
apollo-client/src/main/java/com/ctrip/framework/apollo/spring/annotation/SpringValueProcessor.java
0 → 100644
View file @
5823daa6
package
com
.
ctrip
.
framework
.
apollo
.
spring
.
annotation
;
import
java.beans.PropertyDescriptor
;
import
java.lang.reflect.Field
;
import
java.lang.reflect.Method
;
import
java.util.Collection
;
import
java.util.LinkedList
;
import
java.util.List
;
import
java.util.Objects
;
import
java.util.Set
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.BeanUtils
;
import
org.springframework.beans.BeansException
;
import
org.springframework.beans.TypeConverter
;
import
org.springframework.beans.factory.BeanFactory
;
import
org.springframework.beans.factory.BeanFactoryAware
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.beans.factory.config.BeanDefinition
;
import
org.springframework.beans.factory.config.BeanExpressionContext
;
import
org.springframework.beans.factory.config.BeanFactoryPostProcessor
;
import
org.springframework.beans.factory.config.BeanPostProcessor
;
import
org.springframework.beans.factory.config.ConfigurableBeanFactory
;
import
org.springframework.beans.factory.config.ConfigurableListableBeanFactory
;
import
org.springframework.beans.factory.config.Scope
;
import
org.springframework.context.EnvironmentAware
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.core.Ordered
;
import
org.springframework.core.PriorityOrdered
;
import
org.springframework.core.env.Environment
;
import
org.springframework.util.CollectionUtils
;
import
org.springframework.util.ReflectionUtils
;
import
com.ctrip.framework.apollo.ConfigChangeListener
;
import
com.ctrip.framework.apollo.build.ApolloInjector
;
import
com.ctrip.framework.apollo.model.ConfigChange
;
import
com.ctrip.framework.apollo.model.ConfigChangeEvent
;
import
com.ctrip.framework.apollo.spring.config.ConfigPropertySource
;
import
com.ctrip.framework.apollo.spring.config.ConfigPropertySourceFactory
;
import
com.ctrip.framework.apollo.spring.property.PlaceholderHelper
;
import
com.ctrip.framework.apollo.spring.property.SpringValue
;
import
com.ctrip.framework.apollo.spring.property.SpringValueDefinition
;
import
com.ctrip.framework.apollo.spring.property.SpringValueDefinitionProcessor
;
import
com.ctrip.framework.apollo.util.ConfigUtil
;
import
com.google.common.collect.LinkedListMultimap
;
import
com.google.common.collect.Multimap
;
/**
* Spring value processor of field or method which has @Value and xml config placeholders.
*
* @author github.com/zhegexiaohuozi seimimaster@gmail.com
* @since 2017/12/20.
*/
public
class
SpringValueProcessor
implements
BeanPostProcessor
,
PriorityOrdered
,
EnvironmentAware
,
BeanFactoryAware
,
BeanFactoryPostProcessor
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
SpringValueProcessor
.
class
);
private
final
Multimap
<
String
,
SpringValue
>
monitor
=
LinkedListMultimap
.
create
();
private
final
ConfigUtil
configUtil
;
private
final
PlaceholderHelper
placeholderHelper
;
private
final
ConfigPropertySourceFactory
configPropertySourceFactory
;
private
final
boolean
typeConverterHasConvertIfNecessaryWithFieldParameter
;
private
Environment
environment
;
private
ConfigurableBeanFactory
beanFactory
;
private
TypeConverter
typeConverter
;
private
static
Multimap
<
String
,
SpringValueDefinition
>
beanName2SpringValueDefinitions
=
LinkedListMultimap
.
create
();
public
SpringValueProcessor
()
{
configUtil
=
ApolloInjector
.
getInstance
(
ConfigUtil
.
class
);
placeholderHelper
=
ApolloInjector
.
getInstance
(
PlaceholderHelper
.
class
);
configPropertySourceFactory
=
ApolloInjector
.
getInstance
(
ConfigPropertySourceFactory
.
class
);
typeConverterHasConvertIfNecessaryWithFieldParameter
=
testTypeConverterHasConvertIfNecessaryWithFieldParameter
();
}
@Override
public
void
setBeanFactory
(
BeanFactory
beanFactory
)
throws
BeansException
{
this
.
beanFactory
=
(
ConfigurableBeanFactory
)
beanFactory
;
this
.
typeConverter
=
this
.
beanFactory
.
getTypeConverter
();
}
@Override
public
void
setEnvironment
(
Environment
env
)
{
this
.
environment
=
env
;
}
@Override
public
void
postProcessBeanFactory
(
ConfigurableListableBeanFactory
beanFactory
)
throws
BeansException
{
if
(
configUtil
.
isAutoUpdateInjectedSpringPropertiesEnabled
())
{
beanName2SpringValueDefinitions
=
SpringValueDefinitionProcessor
.
getBeanName2SpringValueDefinitions
();
registerConfigChangeListener
();
}
}
@Override
public
Object
postProcessBeforeInitialization
(
Object
bean
,
String
beanName
)
throws
BeansException
{
if
(
configUtil
.
isAutoUpdateInjectedSpringPropertiesEnabled
())
{
Class
clazz
=
bean
.
getClass
();
processFields
(
bean
,
beanName
,
findAllField
(
clazz
));
processMethods
(
bean
,
beanName
,
findAllMethod
(
clazz
));
processBeanPropertyValues
(
bean
,
beanName
);
}
return
bean
;
}
@Override
public
Object
postProcessAfterInitialization
(
Object
bean
,
String
beanName
)
throws
BeansException
{
return
bean
;
}
private
void
processFields
(
Object
bean
,
String
beanName
,
List
<
Field
>
declaredFields
)
{
for
(
Field
field
:
declaredFields
)
{
// register @Value on field
Value
value
=
field
.
getAnnotation
(
Value
.
class
);
if
(
value
==
null
)
{
continue
;
}
Set
<
String
>
keys
=
placeholderHelper
.
extractPlaceholderKeys
(
value
.
value
());
if
(
keys
.
isEmpty
())
{
continue
;
}
for
(
String
key
:
keys
)
{
SpringValue
springValue
=
new
SpringValue
(
key
,
value
.
value
(),
bean
,
beanName
,
field
);
monitor
.
put
(
key
,
springValue
);
logger
.
debug
(
"Monitoring {}"
,
springValue
);
}
}
}
private
void
processMethods
(
final
Object
bean
,
String
beanName
,
List
<
Method
>
declaredMethods
)
{
for
(
final
Method
method
:
declaredMethods
)
{
//register @Value on method
Value
value
=
method
.
getAnnotation
(
Value
.
class
);
if
(
value
==
null
)
{
continue
;
}
//skip Configuration bean methods
if
(
method
.
getAnnotation
(
Bean
.
class
)
!=
null
)
{
continue
;
}
if
(
method
.
getParameterTypes
().
length
!=
1
)
{
logger
.
error
(
"Ignore @Value setter {}.{}, expecting 1 parameter, actual {} parameters"
,
bean
.
getClass
().
getName
(),
method
.
getName
(),
method
.
getParameterTypes
().
length
);
continue
;
}
Set
<
String
>
keys
=
placeholderHelper
.
extractPlaceholderKeys
(
value
.
value
());
if
(
keys
.
isEmpty
())
{
continue
;
}
for
(
String
key
:
keys
)
{
SpringValue
springValue
=
new
SpringValue
(
key
,
value
.
value
(),
bean
,
beanName
,
method
);
monitor
.
put
(
key
,
springValue
);
logger
.
debug
(
"Monitoring {}"
,
springValue
);
}
}
}
private
void
processBeanPropertyValues
(
Object
bean
,
String
beanName
)
{
Collection
<
SpringValueDefinition
>
propertySpringValues
=
beanName2SpringValueDefinitions
.
get
(
beanName
);
if
(
propertySpringValues
==
null
||
propertySpringValues
.
isEmpty
())
{
return
;
}
for
(
SpringValueDefinition
definition
:
propertySpringValues
)
{
try
{
PropertyDescriptor
pd
=
BeanUtils
.
getPropertyDescriptor
(
bean
.
getClass
(),
definition
.
getPropertyName
());
Method
method
=
pd
.
getWriteMethod
();
if
(
method
==
null
)
{
continue
;
}
SpringValue
springValue
=
new
SpringValue
(
definition
.
getKey
(),
definition
.
getPlaceholder
(),
bean
,
beanName
,
method
);
monitor
.
put
(
definition
.
getKey
(),
springValue
);
logger
.
debug
(
"Monitoring {}"
,
springValue
);
}
catch
(
Throwable
ex
)
{
logger
.
error
(
"Failed to enable auto update feature for {}.{}"
,
bean
.
getClass
(),
definition
.
getPropertyName
());
}
}
// clear
beanName2SpringValueDefinitions
.
removeAll
(
beanName
);
}
private
List
<
Field
>
findAllField
(
Class
clazz
)
{
final
List
<
Field
>
res
=
new
LinkedList
<>();
ReflectionUtils
.
doWithFields
(
clazz
,
new
ReflectionUtils
.
FieldCallback
()
{
@Override
public
void
doWith
(
Field
field
)
throws
IllegalArgumentException
,
IllegalAccessException
{
res
.
add
(
field
);
}
});
return
res
;
}
private
List
<
Method
>
findAllMethod
(
Class
clazz
)
{
final
List
<
Method
>
res
=
new
LinkedList
<>();
ReflectionUtils
.
doWithMethods
(
clazz
,
new
ReflectionUtils
.
MethodCallback
()
{
@Override
public
void
doWith
(
Method
method
)
throws
IllegalArgumentException
,
IllegalAccessException
{
res
.
add
(
method
);
}
});
return
res
;
}
private
void
registerConfigChangeListener
()
{
ConfigChangeListener
changeListener
=
new
ConfigChangeListener
()
{
@Override
public
void
onChange
(
ConfigChangeEvent
changeEvent
)
{
Set
<
String
>
keys
=
changeEvent
.
changedKeys
();
if
(
CollectionUtils
.
isEmpty
(
keys
))
{
return
;
}
for
(
String
key
:
keys
)
{
// 1. check whether the changed key is relevant
Collection
<
SpringValue
>
targetValues
=
monitor
.
get
(
key
);
if
(
targetValues
==
null
||
targetValues
.
isEmpty
())
{
continue
;
}
// 2. check whether the value is really changed or not (since spring property sources have hierarchies)
ConfigChange
configChange
=
changeEvent
.
getChange
(
key
);
if
(!
Objects
.
equals
(
environment
.
getProperty
(
key
),
configChange
.
getNewValue
()))
{
continue
;
}
// 3. update the value
for
(
SpringValue
val
:
targetValues
)
{
updateSpringValue
(
val
);
}
}
}
};
List
<
ConfigPropertySource
>
configPropertySources
=
configPropertySourceFactory
.
getAllConfigPropertySources
();
for
(
ConfigPropertySource
configPropertySource
:
configPropertySources
)
{
configPropertySource
.
addChangeListener
(
changeListener
);
}
}
private
void
updateSpringValue
(
SpringValue
springValue
)
{
try
{
Object
value
=
resolvePropertyValue
(
springValue
);
springValue
.
update
(
value
);
logger
.
debug
(
"Auto update apollo changed value successfully, new value: {}, {}"
,
value
,
springValue
.
toString
());
}
catch
(
Throwable
ex
)
{
logger
.
error
(
"Auto update apollo changed value failed, {}"
,
springValue
.
toString
(),
ex
);
}
}
/**
* Logic transplanted from DefaultListableBeanFactory
* @see org.springframework.beans.factory.support.DefaultListableBeanFactory#doResolveDependency(org.springframework.beans.factory.config.DependencyDescriptor, java.lang.String, java.util.Set, org.springframework.beans.TypeConverter)
*/
private
Object
resolvePropertyValue
(
SpringValue
springValue
)
{
String
strVal
=
beanFactory
.
resolveEmbeddedValue
(
springValue
.
getPlaceholder
());
Object
value
;
BeanDefinition
bd
=
(
beanFactory
.
containsBean
(
springValue
.
getBeanName
())
?
beanFactory
.
getMergedBeanDefinition
(
springValue
.
getBeanName
())
:
null
);
value
=
evaluateBeanDefinitionString
(
strVal
,
bd
);
if
(
springValue
.
isField
())
{
// org.springframework.beans.TypeConverter#convertIfNecessary(java.lang.Object, java.lang.Class, java.lang.reflect.Field) is available from Spring 3.2.0+
if
(
typeConverterHasConvertIfNecessaryWithFieldParameter
)
{
value
=
this
.
typeConverter
.
convertIfNecessary
(
value
,
springValue
.
getTargetType
(),
springValue
.
getField
());
}
else
{
value
=
this
.
typeConverter
.
convertIfNecessary
(
value
,
springValue
.
getTargetType
());
}
}
else
{
value
=
this
.
typeConverter
.
convertIfNecessary
(
value
,
springValue
.
getTargetType
(),
springValue
.
getMethodParameter
());
}
return
value
;
}
private
Object
evaluateBeanDefinitionString
(
String
value
,
BeanDefinition
beanDefinition
)
{
if
(
beanFactory
.
getBeanExpressionResolver
()
==
null
)
{
return
value
;
}
Scope
scope
=
(
beanDefinition
!=
null
?
beanFactory
.
getRegisteredScope
(
beanDefinition
.
getScope
())
:
null
);
return
beanFactory
.
getBeanExpressionResolver
().
evaluate
(
value
,
new
BeanExpressionContext
(
beanFactory
,
scope
));
}
private
boolean
testTypeConverterHasConvertIfNecessaryWithFieldParameter
()
{
try
{
TypeConverter
.
class
.
getMethod
(
"convertIfNecessary"
,
Object
.
class
,
Class
.
class
,
Field
.
class
);
}
catch
(
Throwable
ex
)
{
return
false
;
}
return
true
;
}
@Override
public
int
getOrder
()
{
//make it as late as possible
return
Ordered
.
LOWEST_PRECEDENCE
;
}
}
apollo-client/src/main/java/com/ctrip/framework/apollo/spring/boot/ApolloSpringApplicationRunListener.java
View file @
5823daa6
...
@@ -2,7 +2,9 @@ package com.ctrip.framework.apollo.spring.boot;
...
@@ -2,7 +2,9 @@ package com.ctrip.framework.apollo.spring.boot;
import
com.ctrip.framework.apollo.Config
;
import
com.ctrip.framework.apollo.Config
;
import
com.ctrip.framework.apollo.ConfigService
;
import
com.ctrip.framework.apollo.ConfigService
;
import
com.ctrip.framework.apollo.build.ApolloInjector
;
import
com.ctrip.framework.apollo.core.ConfigConsts
;
import
com.ctrip.framework.apollo.core.ConfigConsts
;
import
com.ctrip.framework.apollo.spring.config.ConfigPropertySourceFactory
;
import
com.ctrip.framework.apollo.spring.config.PropertySourcesConstants
;
import
com.ctrip.framework.apollo.spring.config.PropertySourcesConstants
;
import
com.ctrip.framework.apollo.spring.config.ConfigPropertySource
;
import
com.ctrip.framework.apollo.spring.config.ConfigPropertySource
;
import
com.google.common.base.Splitter
;
import
com.google.common.base.Splitter
;
...
@@ -39,6 +41,9 @@ public class ApolloSpringApplicationRunListener implements SpringApplicationRunL
...
@@ -39,6 +41,9 @@ public class ApolloSpringApplicationRunListener implements SpringApplicationRunL
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
ApolloSpringApplicationRunListener
.
class
);
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
ApolloSpringApplicationRunListener
.
class
);
private
static
final
Splitter
NAMESPACE_SPLITTER
=
Splitter
.
on
(
","
).
omitEmptyStrings
().
trimResults
();
private
static
final
Splitter
NAMESPACE_SPLITTER
=
Splitter
.
on
(
","
).
omitEmptyStrings
().
trimResults
();
private
final
ConfigPropertySourceFactory
configPropertySourceFactory
=
ApolloInjector
.
getInstance
(
ConfigPropertySourceFactory
.
class
);
public
ApolloSpringApplicationRunListener
(
SpringApplication
application
,
String
[]
args
)
{
public
ApolloSpringApplicationRunListener
(
SpringApplication
application
,
String
[]
args
)
{
//ignore
//ignore
}
}
...
@@ -74,7 +79,7 @@ public class ApolloSpringApplicationRunListener implements SpringApplicationRunL
...
@@ -74,7 +79,7 @@ public class ApolloSpringApplicationRunListener implements SpringApplicationRunL
for
(
String
namespace
:
namespaceList
)
{
for
(
String
namespace
:
namespaceList
)
{
Config
config
=
ConfigService
.
getConfig
(
namespace
);
Config
config
=
ConfigService
.
getConfig
(
namespace
);
composite
.
addPropertySource
(
new
ConfigPropertySource
(
namespace
,
config
));
composite
.
addPropertySource
(
configPropertySourceFactory
.
get
ConfigPropertySource
(
namespace
,
config
));
}
}
environment
.
getPropertySources
().
addFirst
(
composite
);
environment
.
getPropertySources
().
addFirst
(
composite
);
...
...
apollo-client/src/main/java/com/ctrip/framework/apollo/spring/config/ConfigPropertySource.java
View file @
5823daa6
package
com
.
ctrip
.
framework
.
apollo
.
spring
.
config
;
package
com
.
ctrip
.
framework
.
apollo
.
spring
.
config
;
import
com.ctrip.framework.apollo.ConfigChangeListener
;
import
java.util.Set
;
import
java.util.Set
;
import
org.springframework.core.env.EnumerablePropertySource
;
import
org.springframework.core.env.EnumerablePropertySource
;
...
@@ -14,7 +15,7 @@ import com.ctrip.framework.apollo.Config;
...
@@ -14,7 +15,7 @@ import com.ctrip.framework.apollo.Config;
public
class
ConfigPropertySource
extends
EnumerablePropertySource
<
Config
>
{
public
class
ConfigPropertySource
extends
EnumerablePropertySource
<
Config
>
{
private
static
final
String
[]
EMPTY_ARRAY
=
new
String
[
0
];
private
static
final
String
[]
EMPTY_ARRAY
=
new
String
[
0
];
public
ConfigPropertySource
(
String
name
,
Config
source
)
{
ConfigPropertySource
(
String
name
,
Config
source
)
{
super
(
name
,
source
);
super
(
name
,
source
);
}
}
...
@@ -31,4 +32,8 @@ public class ConfigPropertySource extends EnumerablePropertySource<Config> {
...
@@ -31,4 +32,8 @@ public class ConfigPropertySource extends EnumerablePropertySource<Config> {
public
Object
getProperty
(
String
name
)
{
public
Object
getProperty
(
String
name
)
{
return
this
.
source
.
getProperty
(
name
,
null
);
return
this
.
source
.
getProperty
(
name
,
null
);
}
}
public
void
addChangeListener
(
ConfigChangeListener
listener
)
{
this
.
source
.
addChangeListener
(
listener
);
}
}
}
apollo-client/src/main/java/com/ctrip/framework/apollo/spring/config/ConfigPropertySourceFactory.java
0 → 100644
View file @
5823daa6
package
com
.
ctrip
.
framework
.
apollo
.
spring
.
config
;
import
java.util.List
;
import
com.ctrip.framework.apollo.Config
;
import
com.google.common.collect.Lists
;
public
class
ConfigPropertySourceFactory
{
private
final
List
<
ConfigPropertySource
>
configPropertySources
=
Lists
.
newLinkedList
();
public
ConfigPropertySource
getConfigPropertySource
(
String
name
,
Config
source
)
{
ConfigPropertySource
configPropertySource
=
new
ConfigPropertySource
(
name
,
source
);
configPropertySources
.
add
(
configPropertySource
);
return
configPropertySource
;
}
public
List
<
ConfigPropertySource
>
getAllConfigPropertySources
()
{
return
Lists
.
newLinkedList
(
configPropertySources
);
}
}
apollo-client/src/main/java/com/ctrip/framework/apollo/spring/config/ConfigPropertySourcesProcessor.java
View file @
5823daa6
package
com
.
ctrip
.
framework
.
apollo
.
spring
.
config
;
package
com
.
ctrip
.
framework
.
apollo
.
spring
.
config
;
import
com.ctrip.framework.apollo.spring.annotation.SpringValueProcessor
;
import
com.ctrip.framework.apollo.spring.property.SpringValueDefinitionProcessor
;
import
org.springframework.beans.BeansException
;
import
org.springframework.beans.BeansException
;
import
org.springframework.beans.factory.support.BeanDefinitionRegistry
;
import
org.springframework.beans.factory.support.BeanDefinitionRegistry
;
import
org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor
;
import
org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor
;
...
@@ -22,5 +24,19 @@ public class ConfigPropertySourcesProcessor extends PropertySourcesProcessor
...
@@ -22,5 +24,19 @@ public class ConfigPropertySourcesProcessor extends PropertySourcesProcessor
PropertySourcesPlaceholderConfigurer
.
class
);
PropertySourcesPlaceholderConfigurer
.
class
);
BeanRegistrationUtil
.
registerBeanDefinitionIfNotExists
(
registry
,
ApolloAnnotationProcessor
.
class
.
getName
(),
BeanRegistrationUtil
.
registerBeanDefinitionIfNotExists
(
registry
,
ApolloAnnotationProcessor
.
class
.
getName
(),
ApolloAnnotationProcessor
.
class
);
ApolloAnnotationProcessor
.
class
);
BeanRegistrationUtil
.
registerBeanDefinitionIfNotExists
(
registry
,
SpringValueProcessor
.
class
.
getName
(),
SpringValueProcessor
.
class
);
processSpringValueDefinition
(
registry
);
}
/**
* For Spring 3.x versions, the BeanDefinitionRegistryPostProcessor would not be
* instantiated if it is added in postProcessBeanDefinitionRegistry phase, so we have to manually
* call the postProcessBeanDefinitionRegistry method of SpringValueDefinitionProcessor here...
*/
private
void
processSpringValueDefinition
(
BeanDefinitionRegistry
registry
)
{
SpringValueDefinitionProcessor
springValueDefinitionProcessor
=
new
SpringValueDefinitionProcessor
();
springValueDefinitionProcessor
.
postProcessBeanDefinitionRegistry
(
registry
);
}
}
}
}
apollo-client/src/main/java/com/ctrip/framework/apollo/spring/config/PropertySourcesProcessor.java
View file @
5823daa6
package
com
.
ctrip
.
framework
.
apollo
.
spring
.
config
;
package
com
.
ctrip
.
framework
.
apollo
.
spring
.
config
;
import
com.ctrip.framework.apollo.build.ApolloInjector
;
import
com.google.common.collect.ImmutableSortedSet
;
import
com.google.common.collect.ImmutableSortedSet
;
import
com.google.common.collect.LinkedHashMultimap
;
import
com.google.common.collect.LinkedHashMultimap
;
import
com.google.common.collect.Multimap
;
import
com.google.common.collect.Multimap
;
...
@@ -33,6 +34,8 @@ import java.util.Iterator;
...
@@ -33,6 +34,8 @@ import java.util.Iterator;
public
class
PropertySourcesProcessor
implements
BeanFactoryPostProcessor
,
EnvironmentAware
,
PriorityOrdered
{
public
class
PropertySourcesProcessor
implements
BeanFactoryPostProcessor
,
EnvironmentAware
,
PriorityOrdered
{
private
static
final
Multimap
<
Integer
,
String
>
NAMESPACE_NAMES
=
LinkedHashMultimap
.
create
();
private
static
final
Multimap
<
Integer
,
String
>
NAMESPACE_NAMES
=
LinkedHashMultimap
.
create
();
private
final
ConfigPropertySourceFactory
configPropertySourceFactory
=
ApolloInjector
.
getInstance
(
ConfigPropertySourceFactory
.
class
);
private
ConfigurableEnvironment
environment
;
private
ConfigurableEnvironment
environment
;
public
static
boolean
addNamespaces
(
Collection
<
String
>
namespaces
,
int
order
)
{
public
static
boolean
addNamespaces
(
Collection
<
String
>
namespaces
,
int
order
)
{
...
@@ -60,7 +63,7 @@ public class PropertySourcesProcessor implements BeanFactoryPostProcessor, Envir
...
@@ -60,7 +63,7 @@ public class PropertySourcesProcessor implements BeanFactoryPostProcessor, Envir
for
(
String
namespace
:
NAMESPACE_NAMES
.
get
(
order
))
{
for
(
String
namespace
:
NAMESPACE_NAMES
.
get
(
order
))
{
Config
config
=
ConfigService
.
getConfig
(
namespace
);
Config
config
=
ConfigService
.
getConfig
(
namespace
);
composite
.
addPropertySource
(
new
ConfigPropertySource
(
namespace
,
config
));
composite
.
addPropertySource
(
configPropertySourceFactory
.
get
ConfigPropertySource
(
namespace
,
config
));
}
}
}
}
...
...
apollo-client/src/main/java/com/ctrip/framework/apollo/spring/property/PlaceholderHelper.java
0 → 100644
View file @
5823daa6
package
com
.
ctrip
.
framework
.
apollo
.
spring
.
property
;
import
com.google.common.base.Strings
;
import
com.google.common.collect.Sets
;
import
java.util.Set
;
import
java.util.Stack
;
import
org.springframework.util.StringUtils
;
/**
* Extract keys from placeholder, e.g.
* <ul>
* <li>${some.key} => "some.key"</li>
* <li>${some.key:${some.other.key:100}} => "some.key", "some.other.key"</li>
* <li>${${some.key}} => "some.key"</li>
* <li>${${some.key:other.key}} => "some.key"</li>
* <li>${${some.key}:${another.key}} => "some.key", "another.key"</li>
* <li>#{new java.text.SimpleDateFormat('${some.key}').parse('${another.key}')} => "some.key", "another.key"</li>
* </ul>
*/
public
class
PlaceholderHelper
{
private
static
final
String
PLACEHOLDER_PREFIX
=
"${"
;
private
static
final
String
PLACEHOLDER_SUFFIX
=
"}"
;
private
static
final
String
VALUE_SEPARATOR
=
":"
;
private
static
final
String
SIMPLE_PLACEHOLDER_PREFIX
=
"{"
;
private
static
final
String
EXPRESSION_PREFIX
=
"#{"
;
private
static
final
String
EXPRESSION_SUFFIX
=
"}"
;
public
Set
<
String
>
extractPlaceholderKeys
(
String
propertyString
)
{
Set
<
String
>
placeholderKeys
=
Sets
.
newHashSet
();
if
(!
isNormalizedPlaceholder
(
propertyString
)
&&
!
isExpressionWithPlaceholder
(
propertyString
))
{
return
placeholderKeys
;
}
Stack
<
String
>
stack
=
new
Stack
<>();
stack
.
push
(
propertyString
);
while
(!
stack
.
isEmpty
())
{
String
strVal
=
stack
.
pop
();
int
startIndex
=
strVal
.
indexOf
(
PLACEHOLDER_PREFIX
);
if
(
startIndex
==
-
1
)
{
placeholderKeys
.
add
(
strVal
);
continue
;
}
int
endIndex
=
findPlaceholderEndIndex
(
strVal
,
startIndex
);
if
(
endIndex
==
-
1
)
{
// invalid placeholder?
continue
;
}
String
placeholderCandidate
=
strVal
.
substring
(
startIndex
+
PLACEHOLDER_PREFIX
.
length
(),
endIndex
);
// ${some.key:other.key}
if
(
placeholderCandidate
.
startsWith
(
PLACEHOLDER_PREFIX
))
{
stack
.
push
(
placeholderCandidate
);
}
else
{
// some.key:${some.other.key:100}
int
separatorIndex
=
placeholderCandidate
.
indexOf
(
VALUE_SEPARATOR
);
if
(
separatorIndex
==
-
1
)
{
stack
.
push
(
placeholderCandidate
);
}
else
{
stack
.
push
(
placeholderCandidate
.
substring
(
0
,
separatorIndex
));
String
defaultValuePart
=
normalizeToPlaceholder
(
placeholderCandidate
.
substring
(
separatorIndex
+
VALUE_SEPARATOR
.
length
()));
if
(!
Strings
.
isNullOrEmpty
(
defaultValuePart
))
{
stack
.
push
(
defaultValuePart
);
}
}
}
// has remaining part, e.g. ${a}.${b}
if
(
endIndex
+
PLACEHOLDER_SUFFIX
.
length
()
<
strVal
.
length
()
-
1
)
{
String
remainingPart
=
normalizeToPlaceholder
(
strVal
.
substring
(
endIndex
+
PLACEHOLDER_SUFFIX
.
length
()));
if
(!
Strings
.
isNullOrEmpty
(
remainingPart
))
{
stack
.
push
(
remainingPart
);
}
}
}
return
placeholderKeys
;
}
private
boolean
isNormalizedPlaceholder
(
String
propertyString
)
{
return
propertyString
.
startsWith
(
PLACEHOLDER_PREFIX
)
&&
propertyString
.
endsWith
(
PLACEHOLDER_SUFFIX
);
}
private
boolean
isExpressionWithPlaceholder
(
String
propertyString
)
{
return
propertyString
.
startsWith
(
EXPRESSION_PREFIX
)
&&
propertyString
.
endsWith
(
EXPRESSION_SUFFIX
)
&&
propertyString
.
contains
(
PLACEHOLDER_PREFIX
);
}
private
String
normalizeToPlaceholder
(
String
strVal
)
{
int
startIndex
=
strVal
.
indexOf
(
PLACEHOLDER_PREFIX
);
if
(
startIndex
==
-
1
)
{
return
null
;
}
int
endIndex
=
strVal
.
lastIndexOf
(
PLACEHOLDER_SUFFIX
);
if
(
endIndex
==
-
1
)
{
return
null
;
}
return
strVal
.
substring
(
startIndex
,
endIndex
+
PLACEHOLDER_SUFFIX
.
length
());
}
private
int
findPlaceholderEndIndex
(
CharSequence
buf
,
int
startIndex
)
{
int
index
=
startIndex
+
PLACEHOLDER_PREFIX
.
length
();
int
withinNestedPlaceholder
=
0
;
while
(
index
<
buf
.
length
())
{
if
(
StringUtils
.
substringMatch
(
buf
,
index
,
PLACEHOLDER_SUFFIX
))
{
if
(
withinNestedPlaceholder
>
0
)
{
withinNestedPlaceholder
--;
index
=
index
+
PLACEHOLDER_SUFFIX
.
length
();
}
else
{
return
index
;
}
}
else
if
(
StringUtils
.
substringMatch
(
buf
,
index
,
SIMPLE_PLACEHOLDER_PREFIX
))
{
withinNestedPlaceholder
++;
index
=
index
+
SIMPLE_PLACEHOLDER_PREFIX
.
length
();
}
else
{
index
++;
}
}
return
-
1
;
}
}
apollo-client/src/main/java/com/ctrip/framework/apollo/spring/property/SpringValue.java
0 → 100644
View file @
5823daa6
package
com
.
ctrip
.
framework
.
apollo
.
spring
.
property
;
import
java.lang.reflect.Field
;
import
java.lang.reflect.InvocationTargetException
;
import
java.lang.reflect.Method
;
import
org.springframework.core.MethodParameter
;
/**
* Spring @Value method info
*
* @author github.com/zhegexiaohuozi seimimaster@gmail.com
* @since 2018/2/6.
*/
public
class
SpringValue
{
private
MethodParameter
methodParameter
;
private
Field
field
;
private
Object
bean
;
private
String
beanName
;
private
String
key
;
private
String
placeholder
;
private
Class
<?>
targetType
;
public
SpringValue
(
String
key
,
String
placeholder
,
Object
bean
,
String
beanName
,
Field
field
)
{
this
.
bean
=
bean
;
this
.
beanName
=
beanName
;
this
.
field
=
field
;
this
.
key
=
key
;
this
.
placeholder
=
placeholder
;
this
.
targetType
=
field
.
getType
();
}
public
SpringValue
(
String
key
,
String
placeholder
,
Object
bean
,
String
beanName
,
Method
method
)
{
this
.
bean
=
bean
;
this
.
beanName
=
beanName
;
this
.
methodParameter
=
new
MethodParameter
(
method
,
0
);
this
.
key
=
key
;
this
.
placeholder
=
placeholder
;
Class
<?>[]
paramTps
=
method
.
getParameterTypes
();
this
.
targetType
=
paramTps
[
0
];
}
public
void
update
(
Object
newVal
)
throws
IllegalAccessException
,
InvocationTargetException
{
if
(
isField
())
{
injectField
(
newVal
);
}
else
{
injectMethod
(
newVal
);
}
}
private
void
injectField
(
Object
newVal
)
throws
IllegalAccessException
{
boolean
accessible
=
field
.
isAccessible
();
field
.
setAccessible
(
true
);
field
.
set
(
bean
,
newVal
);
field
.
setAccessible
(
accessible
);
}
private
void
injectMethod
(
Object
newVal
)
throws
InvocationTargetException
,
IllegalAccessException
{
methodParameter
.
getMethod
().
invoke
(
bean
,
newVal
);
}
public
String
getBeanName
()
{
return
beanName
;
}
public
Class
<?>
getTargetType
()
{
return
targetType
;
}
public
String
getPlaceholder
()
{
return
this
.
placeholder
;
}
public
MethodParameter
getMethodParameter
()
{
return
methodParameter
;
}
public
boolean
isField
()
{
return
this
.
field
!=
null
;
}
public
Field
getField
()
{
return
field
;
}
@Override
public
String
toString
()
{
if
(
isField
())
{
return
String
.
format
(
"key: %s, beanName: %s, field: %s.%s"
,
key
,
beanName
,
bean
.
getClass
().
getName
(),
field
.
getName
());
}
return
String
.
format
(
"key: %s, beanName: %s, method: %s.%s"
,
key
,
beanName
,
bean
.
getClass
().
getName
(),
methodParameter
.
getMethod
().
getName
());
}
}
apollo-client/src/main/java/com/ctrip/framework/apollo/spring/property/SpringValueDefinition.java
0 → 100644
View file @
5823daa6
package
com
.
ctrip
.
framework
.
apollo
.
spring
.
property
;
public
class
SpringValueDefinition
{
private
final
String
key
;
private
final
String
placeholder
;
private
final
String
propertyName
;
public
SpringValueDefinition
(
String
key
,
String
placeholder
,
String
propertyName
)
{
this
.
key
=
key
;
this
.
placeholder
=
placeholder
;
this
.
propertyName
=
propertyName
;
}
public
String
getKey
()
{
return
key
;
}
public
String
getPlaceholder
()
{
return
placeholder
;
}
public
String
getPropertyName
()
{
return
propertyName
;
}
}
apollo-client/src/main/java/com/ctrip/framework/apollo/spring/property/SpringValueDefinitionProcessor.java
0 → 100644
View file @
5823daa6
package
com
.
ctrip
.
framework
.
apollo
.
spring
.
property
;
import
java.util.List
;
import
java.util.Set
;
import
java.util.concurrent.atomic.AtomicBoolean
;
import
org.springframework.beans.BeansException
;
import
org.springframework.beans.MutablePropertyValues
;
import
org.springframework.beans.PropertyValue
;
import
org.springframework.beans.factory.config.BeanDefinition
;
import
org.springframework.beans.factory.config.ConfigurableListableBeanFactory
;
import
org.springframework.beans.factory.config.TypedStringValue
;
import
org.springframework.beans.factory.support.BeanDefinitionRegistry
;
import
org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor
;
import
com.ctrip.framework.apollo.build.ApolloInjector
;
import
com.ctrip.framework.apollo.util.ConfigUtil
;
import
com.google.common.collect.LinkedListMultimap
;
import
com.google.common.collect.Multimap
;
/**
* To process xml config placeholders, e.g.
*
* <pre>
* <bean class="com.ctrip.framework.apollo.demo.spring.xmlConfigDemo.bean.XmlBean">
* <property name="timeout" value="${timeout:200}"/>
* <property name="batch" value="${batch:100}"/>
* </bean>
* </pre>
*/
public
class
SpringValueDefinitionProcessor
implements
BeanDefinitionRegistryPostProcessor
{
private
static
final
Multimap
<
String
,
SpringValueDefinition
>
beanName2SpringValueDefinitions
=
LinkedListMultimap
.
create
();
private
static
final
AtomicBoolean
initialized
=
new
AtomicBoolean
(
false
);
private
final
ConfigUtil
configUtil
;
private
final
PlaceholderHelper
placeholderHelper
;
public
SpringValueDefinitionProcessor
()
{
configUtil
=
ApolloInjector
.
getInstance
(
ConfigUtil
.
class
);
placeholderHelper
=
ApolloInjector
.
getInstance
(
PlaceholderHelper
.
class
);
}
@Override
public
void
postProcessBeanDefinitionRegistry
(
BeanDefinitionRegistry
registry
)
throws
BeansException
{
if
(
configUtil
.
isAutoUpdateInjectedSpringPropertiesEnabled
())
{
processPropertyValues
(
registry
);
}
}
@Override
public
void
postProcessBeanFactory
(
ConfigurableListableBeanFactory
beanFactory
)
throws
BeansException
{
}
public
static
Multimap
<
String
,
SpringValueDefinition
>
getBeanName2SpringValueDefinitions
()
{
return
beanName2SpringValueDefinitions
;
}
private
void
processPropertyValues
(
BeanDefinitionRegistry
beanRegistry
)
{
if
(!
initialized
.
compareAndSet
(
false
,
true
))
{
// already initialized
return
;
}
String
[]
beanNames
=
beanRegistry
.
getBeanDefinitionNames
();
for
(
String
beanName
:
beanNames
)
{
BeanDefinition
beanDefinition
=
beanRegistry
.
getBeanDefinition
(
beanName
);
MutablePropertyValues
mutablePropertyValues
=
beanDefinition
.
getPropertyValues
();
List
<
PropertyValue
>
propertyValues
=
mutablePropertyValues
.
getPropertyValueList
();
for
(
PropertyValue
propertyValue
:
propertyValues
)
{
Object
value
=
propertyValue
.
getValue
();
if
(!(
value
instanceof
TypedStringValue
))
{
continue
;
}
String
placeholder
=
((
TypedStringValue
)
value
).
getValue
();
Set
<
String
>
keys
=
placeholderHelper
.
extractPlaceholderKeys
(
placeholder
);
if
(
keys
.
isEmpty
())
{
continue
;
}
for
(
String
key
:
keys
)
{
beanName2SpringValueDefinitions
.
put
(
beanName
,
new
SpringValueDefinition
(
key
,
placeholder
,
propertyValue
.
getName
()));
}
}
}
}
//only for test
private
static
void
reset
()
{
initialized
.
set
(
false
);
beanName2SpringValueDefinitions
.
clear
();
}
}
apollo-client/src/main/java/com/ctrip/framework/apollo/util/ConfigUtil.java
View file @
5823daa6
...
@@ -33,6 +33,7 @@ public class ConfigUtil {
...
@@ -33,6 +33,7 @@ public class ConfigUtil {
private
long
configCacheExpireTime
=
1
;
//1 minute
private
long
configCacheExpireTime
=
1
;
//1 minute
private
TimeUnit
configCacheExpireTimeUnit
=
TimeUnit
.
MINUTES
;
//1 minute
private
TimeUnit
configCacheExpireTimeUnit
=
TimeUnit
.
MINUTES
;
//1 minute
private
long
longPollingInitialDelayInMills
=
2000
;
//2 seconds
private
long
longPollingInitialDelayInMills
=
2000
;
//2 seconds
private
boolean
autoUpdateInjectedSpringProperties
=
true
;
public
ConfigUtil
()
{
public
ConfigUtil
()
{
initRefreshInterval
();
initRefreshInterval
();
...
@@ -42,6 +43,7 @@ public class ConfigUtil {
...
@@ -42,6 +43,7 @@ public class ConfigUtil {
initQPS
();
initQPS
();
initMaxConfigCacheSize
();
initMaxConfigCacheSize
();
initLongPollingInitialDelayInMills
();
initLongPollingInitialDelayInMills
();
initAutoUpdateInjectedSpringProperties
();
}
}
/**
/**
...
@@ -263,4 +265,20 @@ public class ConfigUtil {
...
@@ -263,4 +265,20 @@ public class ConfigUtil {
public
long
getLongPollingInitialDelayInMills
()
{
public
long
getLongPollingInitialDelayInMills
()
{
return
longPollingInitialDelayInMills
;
return
longPollingInitialDelayInMills
;
}
}
private
void
initAutoUpdateInjectedSpringProperties
()
{
// 1. Get from System Property
String
enableAutoUpdate
=
System
.
getProperty
(
"apollo.autoUpdateInjectedSpringProperties"
);
if
(
Strings
.
isNullOrEmpty
(
enableAutoUpdate
))
{
// 2. Get from app.properties
enableAutoUpdate
=
Foundation
.
app
().
getProperty
(
"apollo.autoUpdateInjectedSpringProperties"
,
null
);
}
if
(!
Strings
.
isNullOrEmpty
(
enableAutoUpdate
))
{
autoUpdateInjectedSpringProperties
=
Boolean
.
parseBoolean
(
enableAutoUpdate
.
trim
());
}
}
public
boolean
isAutoUpdateInjectedSpringPropertiesEnabled
()
{
return
autoUpdateInjectedSpringProperties
;
}
}
}
apollo-client/src/test/java/com/ctrip/framework/apollo/AllTests.java
View file @
5823daa6
package
com
.
ctrip
.
framework
.
apollo
;
package
com
.
ctrip
.
framework
.
apollo
;
import
com.ctrip.framework.apollo.spring.BootstrapConfigTest
;
import
org.junit.runner.RunWith
;
import
org.junit.runners.Suite
;
import
org.junit.runners.Suite.SuiteClasses
;
import
com.ctrip.framework.apollo.integration.ConfigIntegrationTest
;
import
com.ctrip.framework.apollo.integration.ConfigIntegrationTest
;
import
com.ctrip.framework.apollo.internals.DefaultConfigManagerTest
;
import
com.ctrip.framework.apollo.internals.DefaultConfigManagerTest
;
import
com.ctrip.framework.apollo.internals.DefaultConfigTest
;
import
com.ctrip.framework.apollo.internals.DefaultConfigTest
;
...
@@ -19,24 +13,35 @@ import com.ctrip.framework.apollo.internals.XmlConfigFileTest;
...
@@ -19,24 +13,35 @@ import com.ctrip.framework.apollo.internals.XmlConfigFileTest;
import
com.ctrip.framework.apollo.spi.DefaultConfigFactoryManagerTest
;
import
com.ctrip.framework.apollo.spi.DefaultConfigFactoryManagerTest
;
import
com.ctrip.framework.apollo.spi.DefaultConfigFactoryTest
;
import
com.ctrip.framework.apollo.spi.DefaultConfigFactoryTest
;
import
com.ctrip.framework.apollo.spi.DefaultConfigRegistryTest
;
import
com.ctrip.framework.apollo.spi.DefaultConfigRegistryTest
;
import
com.ctrip.framework.apollo.spring.BootstrapConfigTest
;
import
com.ctrip.framework.apollo.spring.JavaConfigAnnotationTest
;
import
com.ctrip.framework.apollo.spring.JavaConfigAnnotationTest
;
import
com.ctrip.framework.apollo.spring.JavaConfigPlaceholderAutoUpdateTest
;
import
com.ctrip.framework.apollo.spring.JavaConfigPlaceholderTest
;
import
com.ctrip.framework.apollo.spring.JavaConfigPlaceholderTest
;
import
com.ctrip.framework.apollo.spring.XMLConfigAnnotationTest
;
import
com.ctrip.framework.apollo.spring.XMLConfigAnnotationTest
;
import
com.ctrip.framework.apollo.spring.XmlConfigPlaceholderAutoUpdateTest
;
import
com.ctrip.framework.apollo.spring.XmlConfigPlaceholderTest
;
import
com.ctrip.framework.apollo.spring.XmlConfigPlaceholderTest
;
import
com.ctrip.framework.apollo.spring.config.ConfigPropertySourceTest
;
import
com.ctrip.framework.apollo.spring.property.PlaceholderHelperTest
;
import
com.ctrip.framework.apollo.util.ConfigUtilTest
;
import
com.ctrip.framework.apollo.util.ConfigUtilTest
;
import
com.ctrip.framework.apollo.util.ExceptionUtilTest
;
import
com.ctrip.framework.apollo.util.ExceptionUtilTest
;
import
com.ctrip.framework.apollo.util.parser.DateParserTest
;
import
com.ctrip.framework.apollo.util.parser.DateParserTest
;
import
com.ctrip.framework.apollo.util.parser.DurationParserTest
;
import
com.ctrip.framework.apollo.util.parser.DurationParserTest
;
import
org.junit.runner.RunWith
;
import
org.junit.runners.Suite
;
import
org.junit.runners.Suite.SuiteClasses
;
@RunWith
(
Suite
.
class
)
@RunWith
(
Suite
.
class
)
@SuiteClasses
({
@SuiteClasses
({
ConfigServiceTest
.
class
,
DefaultConfigRegistryTest
.
class
,
DefaultConfigFactoryManagerTest
.
class
,
ConfigServiceTest
.
class
,
DefaultConfigRegistryTest
.
class
,
DefaultConfigFactoryManagerTest
.
class
,
DefaultConfigManagerTest
.
class
,
DefaultConfigTest
.
class
,
LocalFileConfigRepositoryTest
.
class
,
DefaultConfigManagerTest
.
class
,
DefaultConfigTest
.
class
,
LocalFileConfigRepositoryTest
.
class
,
RemoteConfigRepositoryTest
.
class
,
SimpleConfigTest
.
class
,
DefaultConfigFactoryTest
.
class
,
RemoteConfigRepositoryTest
.
class
,
SimpleConfigTest
.
class
,
DefaultConfigFactoryTest
.
class
,
ConfigIntegrationTest
.
class
,
ExceptionUtilTest
.
class
,
XmlConfigFileTest
.
class
,
PropertiesConfigFileTest
.
class
,
ConfigIntegrationTest
.
class
,
ExceptionUtilTest
.
class
,
XmlConfigFileTest
.
class
,
RemoteConfigLongPollServiceTest
.
class
,
DateParserTest
.
class
,
DurationParserTest
.
class
,
JsonConfigFileTest
.
class
,
PropertiesConfigFileTest
.
class
,
RemoteConfigLongPollServiceTest
.
class
,
DateParserTest
.
class
,
XmlConfigPlaceholderTest
.
class
,
JavaConfigPlaceholderTest
.
class
,
XMLConfigAnnotationTest
.
class
,
DurationParserTest
.
class
,
JsonConfigFileTest
.
class
,
XmlConfigPlaceholderTest
.
class
,
JavaConfigAnnotationTest
.
class
,
ConfigUtilTest
.
class
,
BootstrapConfigTest
.
class
JavaConfigPlaceholderTest
.
class
,
XMLConfigAnnotationTest
.
class
,
JavaConfigAnnotationTest
.
class
,
ConfigUtilTest
.
class
,
BootstrapConfigTest
.
class
,
JavaConfigPlaceholderAutoUpdateTest
.
class
,
XmlConfigPlaceholderAutoUpdateTest
.
class
,
ConfigPropertySourceTest
.
class
,
PlaceholderHelperTest
.
class
})
})
public
class
AllTests
{
public
class
AllTests
{
...
...
apollo-client/src/test/java/com/ctrip/framework/apollo/build/MockInjector.java
View file @
5823daa6
...
@@ -59,6 +59,5 @@ public class MockInjector implements Injector {
...
@@ -59,6 +59,5 @@ public class MockInjector implements Injector {
public
static
void
reset
()
{
public
static
void
reset
()
{
classMap
.
clear
();
classMap
.
clear
();
classTable
.
clear
();
classTable
.
clear
();
delegate
=
null
;
}
}
}
}
apollo-client/src/test/java/com/ctrip/framework/apollo/spring/AbstractSpringIntegrationTest.java
View file @
5823daa6
package
com
.
ctrip
.
framework
.
apollo
.
spring
;
package
com
.
ctrip
.
framework
.
apollo
.
spring
;
import
static
org
.
mockito
.
Mockito
.
mock
;
import
static
org
.
mockito
.
Mockito
.
when
;
import
com.ctrip.framework.apollo.core.ConfigConsts
;
import
com.ctrip.framework.apollo.internals.ConfigRepository
;
import
com.ctrip.framework.apollo.internals.SimpleConfig
;
import
com.ctrip.framework.apollo.spring.property.SpringValueDefinitionProcessor
;
import
com.ctrip.framework.apollo.util.ConfigUtil
;
import
java.lang.reflect.Method
;
import
java.lang.reflect.Method
;
import
java.util.Calendar
;
import
java.util.Date
;
import
java.util.Map
;
import
java.util.Map
;
import
java.util.Properties
;
import
org.junit.After
;
import
org.junit.After
;
import
org.junit.Before
;
import
org.junit.Before
;
import
org.springframework.util.ReflectionUtils
;
import
org.springframework.util.ReflectionUtils
;
...
@@ -22,12 +33,15 @@ import com.google.common.collect.Maps;
...
@@ -22,12 +33,15 @@ import com.google.common.collect.Maps;
public
abstract
class
AbstractSpringIntegrationTest
{
public
abstract
class
AbstractSpringIntegrationTest
{
private
static
final
Map
<
String
,
Config
>
CONFIG_REGISTRY
=
Maps
.
newHashMap
();
private
static
final
Map
<
String
,
Config
>
CONFIG_REGISTRY
=
Maps
.
newHashMap
();
private
static
Method
PROPERTY_SOURCES_PROCESSOR_CLEAR
;
private
static
Method
PROPERTY_SOURCES_PROCESSOR_CLEAR
;
private
static
Method
SPRING_VALUE_DEFINITION_PROCESS_CLEAR
;
private
static
Method
CONFIG_SERVICE_RESET
;
private
static
Method
CONFIG_SERVICE_RESET
;
static
{
static
{
try
{
try
{
PROPERTY_SOURCES_PROCESSOR_CLEAR
=
PropertySourcesProcessor
.
class
.
getDeclaredMethod
(
"reset"
);
PROPERTY_SOURCES_PROCESSOR_CLEAR
=
PropertySourcesProcessor
.
class
.
getDeclaredMethod
(
"reset"
);
ReflectionUtils
.
makeAccessible
(
PROPERTY_SOURCES_PROCESSOR_CLEAR
);
ReflectionUtils
.
makeAccessible
(
PROPERTY_SOURCES_PROCESSOR_CLEAR
);
SPRING_VALUE_DEFINITION_PROCESS_CLEAR
=
SpringValueDefinitionProcessor
.
class
.
getDeclaredMethod
(
"reset"
);
ReflectionUtils
.
makeAccessible
(
SPRING_VALUE_DEFINITION_PROCESS_CLEAR
);
CONFIG_SERVICE_RESET
=
ConfigService
.
class
.
getDeclaredMethod
(
"reset"
);
CONFIG_SERVICE_RESET
=
ConfigService
.
class
.
getDeclaredMethod
(
"reset"
);
ReflectionUtils
.
makeAccessible
(
CONFIG_SERVICE_RESET
);
ReflectionUtils
.
makeAccessible
(
CONFIG_SERVICE_RESET
);
}
catch
(
NoSuchMethodException
e
)
{
}
catch
(
NoSuchMethodException
e
)
{
...
@@ -45,6 +59,53 @@ public abstract class AbstractSpringIntegrationTest {
...
@@ -45,6 +59,53 @@ public abstract class AbstractSpringIntegrationTest {
doTearDown
();
doTearDown
();
}
}
protected
SimpleConfig
prepareConfig
(
String
namespaceName
,
Properties
properties
)
{
ConfigRepository
configRepository
=
mock
(
ConfigRepository
.
class
);
when
(
configRepository
.
getConfig
()).
thenReturn
(
properties
);
SimpleConfig
config
=
new
SimpleConfig
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
configRepository
);
mockConfig
(
namespaceName
,
config
);
return
config
;
}
protected
Properties
assembleProperties
(
String
key
,
String
value
)
{
Properties
properties
=
new
Properties
();
properties
.
setProperty
(
key
,
value
);
return
properties
;
}
protected
Properties
assembleProperties
(
String
key
,
String
value
,
String
key2
,
String
value2
)
{
Properties
properties
=
new
Properties
();
properties
.
setProperty
(
key
,
value
);
properties
.
setProperty
(
key2
,
value2
);
return
properties
;
}
protected
Properties
assembleProperties
(
String
key
,
String
value
,
String
key2
,
String
value2
,
String
key3
,
String
value3
)
{
Properties
properties
=
new
Properties
();
properties
.
setProperty
(
key
,
value
);
properties
.
setProperty
(
key2
,
value2
);
properties
.
setProperty
(
key3
,
value3
);
return
properties
;
}
protected
Date
assembleDate
(
int
year
,
int
month
,
int
day
,
int
hour
,
int
minute
,
int
second
,
int
millisecond
)
{
Calendar
date
=
Calendar
.
getInstance
();
date
.
set
(
year
,
month
-
1
,
day
,
hour
,
minute
,
second
);
//Month in Calendar is 0 based
date
.
set
(
Calendar
.
MILLISECOND
,
millisecond
);
return
date
.
getTime
();
}
protected
static
void
mockConfig
(
String
namespace
,
Config
config
)
{
protected
static
void
mockConfig
(
String
namespace
,
Config
config
)
{
CONFIG_REGISTRY
.
put
(
namespace
,
config
);
CONFIG_REGISTRY
.
put
(
namespace
,
config
);
}
}
...
@@ -52,6 +113,8 @@ public abstract class AbstractSpringIntegrationTest {
...
@@ -52,6 +113,8 @@ public abstract class AbstractSpringIntegrationTest {
protected
static
void
doSetUp
()
{
protected
static
void
doSetUp
()
{
//as PropertySourcesProcessor has some static states, so we must manually clear its state
//as PropertySourcesProcessor has some static states, so we must manually clear its state
ReflectionUtils
.
invokeMethod
(
PROPERTY_SOURCES_PROCESSOR_CLEAR
,
null
);
ReflectionUtils
.
invokeMethod
(
PROPERTY_SOURCES_PROCESSOR_CLEAR
,
null
);
//as SpringValueDefinitionProcessor has some static states, so we must manually clear its state
ReflectionUtils
.
invokeMethod
(
SPRING_VALUE_DEFINITION_PROCESS_CLEAR
,
null
);
//as ConfigService is singleton, so we must manually clear its container
//as ConfigService is singleton, so we must manually clear its container
ReflectionUtils
.
invokeMethod
(
CONFIG_SERVICE_RESET
,
null
);
ReflectionUtils
.
invokeMethod
(
CONFIG_SERVICE_RESET
,
null
);
MockInjector
.
reset
();
MockInjector
.
reset
();
...
@@ -62,7 +125,7 @@ public abstract class AbstractSpringIntegrationTest {
...
@@ -62,7 +125,7 @@ public abstract class AbstractSpringIntegrationTest {
CONFIG_REGISTRY
.
clear
();
CONFIG_REGISTRY
.
clear
();
}
}
p
ublic
static
class
MockConfigManager
implements
ConfigManager
{
p
rivate
static
class
MockConfigManager
implements
ConfigManager
{
@Override
@Override
public
Config
getConfig
(
String
namespace
)
{
public
Config
getConfig
(
String
namespace
)
{
...
@@ -74,4 +137,18 @@ public abstract class AbstractSpringIntegrationTest {
...
@@ -74,4 +137,18 @@ public abstract class AbstractSpringIntegrationTest {
return
null
;
return
null
;
}
}
}
}
protected
static
class
MockConfigUtil
extends
ConfigUtil
{
private
boolean
isAutoUpdateInjectedSpringProperties
;
public
void
setAutoUpdateInjectedSpringProperties
(
boolean
autoUpdateInjectedSpringProperties
)
{
isAutoUpdateInjectedSpringProperties
=
autoUpdateInjectedSpringProperties
;
}
@Override
public
boolean
isAutoUpdateInjectedSpringPropertiesEnabled
()
{
return
isAutoUpdateInjectedSpringProperties
;
}
}
}
}
apollo-client/src/test/java/com/ctrip/framework/apollo/spring/JavaConfigAnnotationTest.java
View file @
5823daa6
...
@@ -88,7 +88,8 @@ public class JavaConfigAnnotationTest extends AbstractSpringIntegrationTest {
...
@@ -88,7 +88,8 @@ public class JavaConfigAnnotationTest extends AbstractSpringIntegrationTest {
TestApolloConfigChangeListenerBean1
bean
=
getBean
(
TestApolloConfigChangeListenerBean1
.
class
,
AppConfig3
.
class
);
TestApolloConfigChangeListenerBean1
bean
=
getBean
(
TestApolloConfigChangeListenerBean1
.
class
,
AppConfig3
.
class
);
assertEquals
(
3
,
applicationListeners
.
size
());
//PropertySourcesProcessor add listeners to listen config changed of all namespace
assertEquals
(
4
,
applicationListeners
.
size
());
assertEquals
(
1
,
fxApolloListeners
.
size
());
assertEquals
(
1
,
fxApolloListeners
.
size
());
for
(
ConfigChangeListener
listener
:
applicationListeners
)
{
for
(
ConfigChangeListener
listener
:
applicationListeners
)
{
...
...
apollo-client/src/test/java/com/ctrip/framework/apollo/spring/JavaConfigPlaceholderAutoUpdateTest.java
0 → 100644
View file @
5823daa6
package
com
.
ctrip
.
framework
.
apollo
.
spring
;
import
static
org
.
junit
.
Assert
.
assertArrayEquals
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
java.text.SimpleDateFormat
;
import
java.util.Date
;
import
java.util.Locale
;
import
java.util.Properties
;
import
java.util.concurrent.TimeUnit
;
import
org.junit.Test
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.context.annotation.AnnotationConfigApplicationContext
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.ComponentScan
;
import
org.springframework.context.annotation.ComponentScan.Filter
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.context.annotation.FilterType
;
import
org.springframework.context.annotation.ImportResource
;
import
org.springframework.stereotype.Component
;
import
com.ctrip.framework.apollo.build.MockInjector
;
import
com.ctrip.framework.apollo.core.ConfigConsts
;
import
com.ctrip.framework.apollo.internals.SimpleConfig
;
import
com.ctrip.framework.apollo.spring.XmlConfigPlaceholderTest.TestXmlBean
;
import
com.ctrip.framework.apollo.spring.annotation.EnableApolloConfig
;
import
com.ctrip.framework.apollo.util.ConfigUtil
;
import
com.google.common.primitives.Ints
;
public
class
JavaConfigPlaceholderAutoUpdateTest
extends
AbstractSpringIntegrationTest
{
private
static
final
String
TIMEOUT_PROPERTY
=
"timeout"
;
private
static
final
int
DEFAULT_TIMEOUT
=
100
;
private
static
final
String
BATCH_PROPERTY
=
"batch"
;
private
static
final
int
DEFAULT_BATCH
=
200
;
private
static
final
String
FX_APOLLO_NAMESPACE
=
"FX.apollo"
;
private
static
final
String
SOME_KEY_PROPERTY
=
"someKey"
;
private
static
final
String
ANOTHER_KEY_PROPERTY
=
"anotherKey"
;
@Test
public
void
testAutoUpdateWithOneNamespace
()
throws
Exception
{
int
initialTimeout
=
1000
;
int
initialBatch
=
2000
;
int
newTimeout
=
1001
;
int
newBatch
=
2001
;
Properties
properties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
initialTimeout
),
BATCH_PROPERTY
,
String
.
valueOf
(
initialBatch
));
SimpleConfig
config
=
prepareConfig
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
properties
);
AnnotationConfigApplicationContext
context
=
new
AnnotationConfigApplicationContext
(
AppConfig1
.
class
);
TestJavaConfigBean
bean
=
context
.
getBean
(
TestJavaConfigBean
.
class
);
assertEquals
(
initialTimeout
,
bean
.
getTimeout
());
assertEquals
(
initialBatch
,
bean
.
getBatch
());
Properties
newProperties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
newTimeout
),
BATCH_PROPERTY
,
String
.
valueOf
(
newBatch
));
config
.
onRepositoryChange
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
newProperties
);
TimeUnit
.
MILLISECONDS
.
sleep
(
50
);
assertEquals
(
newTimeout
,
bean
.
getTimeout
());
assertEquals
(
newBatch
,
bean
.
getBatch
());
}
@Test
public
void
testAutoUpdateWithValueAndXmlProperty
()
throws
Exception
{
int
initialTimeout
=
1000
;
int
initialBatch
=
2000
;
int
newTimeout
=
1001
;
int
newBatch
=
2001
;
Properties
properties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
initialTimeout
),
BATCH_PROPERTY
,
String
.
valueOf
(
initialBatch
));
SimpleConfig
config
=
prepareConfig
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
properties
);
AnnotationConfigApplicationContext
context
=
new
AnnotationConfigApplicationContext
(
AppConfig8
.
class
);
TestJavaConfigBean
javaConfigBean
=
context
.
getBean
(
TestJavaConfigBean
.
class
);
TestXmlBean
xmlBean
=
context
.
getBean
(
TestXmlBean
.
class
);
assertEquals
(
initialTimeout
,
javaConfigBean
.
getTimeout
());
assertEquals
(
initialBatch
,
javaConfigBean
.
getBatch
());
assertEquals
(
initialTimeout
,
xmlBean
.
getTimeout
());
assertEquals
(
initialBatch
,
xmlBean
.
getBatch
());
Properties
newProperties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
newTimeout
),
BATCH_PROPERTY
,
String
.
valueOf
(
newBatch
));
config
.
onRepositoryChange
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
newProperties
);
TimeUnit
.
MILLISECONDS
.
sleep
(
50
);
assertEquals
(
newTimeout
,
javaConfigBean
.
getTimeout
());
assertEquals
(
newBatch
,
javaConfigBean
.
getBatch
());
assertEquals
(
newTimeout
,
xmlBean
.
getTimeout
());
assertEquals
(
newBatch
,
xmlBean
.
getBatch
());
}
@Test
public
void
testAutoUpdateDisabled
()
throws
Exception
{
int
initialTimeout
=
1000
;
int
initialBatch
=
2000
;
int
newTimeout
=
1001
;
int
newBatch
=
2001
;
MockConfigUtil
mockConfigUtil
=
new
MockConfigUtil
();
mockConfigUtil
.
setAutoUpdateInjectedSpringProperties
(
false
);
MockInjector
.
setInstance
(
ConfigUtil
.
class
,
mockConfigUtil
);
Properties
properties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
initialTimeout
),
BATCH_PROPERTY
,
String
.
valueOf
(
initialBatch
));
SimpleConfig
config
=
prepareConfig
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
properties
);
AnnotationConfigApplicationContext
context
=
new
AnnotationConfigApplicationContext
(
AppConfig1
.
class
);
TestJavaConfigBean
bean
=
context
.
getBean
(
TestJavaConfigBean
.
class
);
assertEquals
(
initialTimeout
,
bean
.
getTimeout
());
assertEquals
(
initialBatch
,
bean
.
getBatch
());
Properties
newProperties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
newTimeout
),
BATCH_PROPERTY
,
String
.
valueOf
(
newBatch
));
config
.
onRepositoryChange
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
newProperties
);
TimeUnit
.
MILLISECONDS
.
sleep
(
50
);
assertEquals
(
initialTimeout
,
bean
.
getTimeout
());
assertEquals
(
initialBatch
,
bean
.
getBatch
());
}
@Test
public
void
testAutoUpdateWithMultipleNamespaces
()
throws
Exception
{
int
initialTimeout
=
1000
;
int
initialBatch
=
2000
;
int
newTimeout
=
1001
;
int
newBatch
=
2001
;
Properties
applicationProperties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
initialTimeout
));
Properties
fxApolloProperties
=
assembleProperties
(
BATCH_PROPERTY
,
String
.
valueOf
(
initialBatch
));
SimpleConfig
applicationConfig
=
prepareConfig
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
applicationProperties
);
SimpleConfig
fxApolloConfig
=
prepareConfig
(
FX_APOLLO_NAMESPACE
,
fxApolloProperties
);
AnnotationConfigApplicationContext
context
=
new
AnnotationConfigApplicationContext
(
AppConfig2
.
class
);
TestJavaConfigBean
bean
=
context
.
getBean
(
TestJavaConfigBean
.
class
);
assertEquals
(
initialTimeout
,
bean
.
getTimeout
());
assertEquals
(
initialBatch
,
bean
.
getBatch
());
Properties
newApplicationProperties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
newTimeout
));
applicationConfig
.
onRepositoryChange
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
newApplicationProperties
);
TimeUnit
.
MILLISECONDS
.
sleep
(
50
);
assertEquals
(
newTimeout
,
bean
.
getTimeout
());
assertEquals
(
initialBatch
,
bean
.
getBatch
());
Properties
newFxApolloProperties
=
assembleProperties
(
BATCH_PROPERTY
,
String
.
valueOf
(
newBatch
));
fxApolloConfig
.
onRepositoryChange
(
FX_APOLLO_NAMESPACE
,
newFxApolloProperties
);
TimeUnit
.
MILLISECONDS
.
sleep
(
50
);
assertEquals
(
newTimeout
,
bean
.
getTimeout
());
assertEquals
(
newBatch
,
bean
.
getBatch
());
}
@Test
public
void
testAutoUpdateWithMultipleNamespacesWithSameProperties
()
throws
Exception
{
int
someTimeout
=
1000
;
int
someBatch
=
2000
;
int
anotherBatch
=
3000
;
int
someNewTimeout
=
1001
;
int
someNewBatch
=
2001
;
Properties
applicationProperties
=
assembleProperties
(
BATCH_PROPERTY
,
String
.
valueOf
(
someBatch
));
Properties
fxApolloProperties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
someTimeout
),
BATCH_PROPERTY
,
String
.
valueOf
(
anotherBatch
));
SimpleConfig
applicationConfig
=
prepareConfig
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
applicationProperties
);
SimpleConfig
fxApolloConfig
=
prepareConfig
(
FX_APOLLO_NAMESPACE
,
fxApolloProperties
);
AnnotationConfigApplicationContext
context
=
new
AnnotationConfigApplicationContext
(
AppConfig2
.
class
);
TestJavaConfigBean
bean
=
context
.
getBean
(
TestJavaConfigBean
.
class
);
assertEquals
(
someTimeout
,
bean
.
getTimeout
());
assertEquals
(
someBatch
,
bean
.
getBatch
());
Properties
newFxApolloProperties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
someNewTimeout
),
BATCH_PROPERTY
,
String
.
valueOf
(
someNewBatch
));
fxApolloConfig
.
onRepositoryChange
(
FX_APOLLO_NAMESPACE
,
newFxApolloProperties
);
TimeUnit
.
MILLISECONDS
.
sleep
(
50
);
assertEquals
(
someNewTimeout
,
bean
.
getTimeout
());
assertEquals
(
someBatch
,
bean
.
getBatch
());
}
@Test
public
void
testAutoUpdateWithNewProperties
()
throws
Exception
{
int
initialTimeout
=
1000
;
int
newTimeout
=
1001
;
int
newBatch
=
2001
;
Properties
applicationProperties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
initialTimeout
));
SimpleConfig
applicationConfig
=
prepareConfig
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
applicationProperties
);
AnnotationConfigApplicationContext
context
=
new
AnnotationConfigApplicationContext
(
AppConfig1
.
class
);
TestJavaConfigBean
bean
=
context
.
getBean
(
TestJavaConfigBean
.
class
);
assertEquals
(
initialTimeout
,
bean
.
getTimeout
());
assertEquals
(
DEFAULT_BATCH
,
bean
.
getBatch
());
Properties
newApplicationProperties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
newTimeout
),
BATCH_PROPERTY
,
String
.
valueOf
(
newBatch
));
applicationConfig
.
onRepositoryChange
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
newApplicationProperties
);
TimeUnit
.
MILLISECONDS
.
sleep
(
50
);
assertEquals
(
newTimeout
,
bean
.
getTimeout
());
assertEquals
(
newBatch
,
bean
.
getBatch
());
}
@Test
public
void
testAutoUpdateWithIrrelevantProperties
()
throws
Exception
{
int
initialTimeout
=
1000
;
String
someIrrelevantKey
=
"someIrrelevantKey"
;
String
someIrrelevantValue
=
"someIrrelevantValue"
;
String
anotherIrrelevantKey
=
"anotherIrrelevantKey"
;
String
anotherIrrelevantValue
=
"anotherIrrelevantValue"
;
Properties
applicationProperties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
initialTimeout
),
someIrrelevantKey
,
someIrrelevantValue
);
SimpleConfig
applicationConfig
=
prepareConfig
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
applicationProperties
);
AnnotationConfigApplicationContext
context
=
new
AnnotationConfigApplicationContext
(
AppConfig1
.
class
);
TestJavaConfigBean
bean
=
context
.
getBean
(
TestJavaConfigBean
.
class
);
assertEquals
(
initialTimeout
,
bean
.
getTimeout
());
assertEquals
(
DEFAULT_BATCH
,
bean
.
getBatch
());
Properties
newApplicationProperties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
initialTimeout
),
anotherIrrelevantKey
,
String
.
valueOf
(
anotherIrrelevantValue
));
applicationConfig
.
onRepositoryChange
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
newApplicationProperties
);
TimeUnit
.
MILLISECONDS
.
sleep
(
50
);
assertEquals
(
initialTimeout
,
bean
.
getTimeout
());
assertEquals
(
DEFAULT_BATCH
,
bean
.
getBatch
());
}
@Test
public
void
testAutoUpdateWithDeletedProperties
()
throws
Exception
{
int
initialTimeout
=
1000
;
int
initialBatch
=
2000
;
Properties
properties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
initialTimeout
),
BATCH_PROPERTY
,
String
.
valueOf
(
initialBatch
));
SimpleConfig
config
=
prepareConfig
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
properties
);
AnnotationConfigApplicationContext
context
=
new
AnnotationConfigApplicationContext
(
AppConfig1
.
class
);
TestJavaConfigBean
bean
=
context
.
getBean
(
TestJavaConfigBean
.
class
);
assertEquals
(
initialTimeout
,
bean
.
getTimeout
());
assertEquals
(
initialBatch
,
bean
.
getBatch
());
Properties
newProperties
=
new
Properties
();
config
.
onRepositoryChange
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
newProperties
);
TimeUnit
.
MILLISECONDS
.
sleep
(
50
);
assertEquals
(
DEFAULT_TIMEOUT
,
bean
.
getTimeout
());
assertEquals
(
DEFAULT_BATCH
,
bean
.
getBatch
());
}
@Test
public
void
testAutoUpdateWithDeletedPropertiesWithNoDefaultValue
()
throws
Exception
{
int
initialTimeout
=
1000
;
int
initialBatch
=
2000
;
int
newTimeout
=
1001
;
Properties
properties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
initialTimeout
),
BATCH_PROPERTY
,
String
.
valueOf
(
initialBatch
));
SimpleConfig
config
=
prepareConfig
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
properties
);
AnnotationConfigApplicationContext
context
=
new
AnnotationConfigApplicationContext
(
AppConfig6
.
class
);
TestJavaConfigBean5
bean
=
context
.
getBean
(
TestJavaConfigBean5
.
class
);
assertEquals
(
initialTimeout
,
bean
.
getTimeout
());
assertEquals
(
initialBatch
,
bean
.
getBatch
());
Properties
newProperties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
newTimeout
));
config
.
onRepositoryChange
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
newProperties
);
TimeUnit
.
MILLISECONDS
.
sleep
(
50
);
assertEquals
(
newTimeout
,
bean
.
getTimeout
());
assertEquals
(
initialBatch
,
bean
.
getBatch
());
}
@Test
public
void
testAutoUpdateWithTypeMismatch
()
throws
Exception
{
int
initialTimeout
=
1000
;
int
initialBatch
=
2000
;
int
newTimeout
=
1001
;
String
newBatch
=
"newBatch"
;
Properties
properties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
initialTimeout
),
BATCH_PROPERTY
,
String
.
valueOf
(
initialBatch
));
SimpleConfig
config
=
prepareConfig
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
properties
);
AnnotationConfigApplicationContext
context
=
new
AnnotationConfigApplicationContext
(
AppConfig1
.
class
);
TestJavaConfigBean
bean
=
context
.
getBean
(
TestJavaConfigBean
.
class
);
assertEquals
(
initialTimeout
,
bean
.
getTimeout
());
assertEquals
(
initialBatch
,
bean
.
getBatch
());
Properties
newProperties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
newTimeout
),
BATCH_PROPERTY
,
newBatch
);
config
.
onRepositoryChange
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
newProperties
);
TimeUnit
.
MILLISECONDS
.
sleep
(
50
);
assertEquals
(
newTimeout
,
bean
.
getTimeout
());
assertEquals
(
initialBatch
,
bean
.
getBatch
());
}
@Test
public
void
testAutoUpdateWithValueInjectedAsParameter
()
throws
Exception
{
int
initialTimeout
=
1000
;
int
initialBatch
=
2000
;
int
newTimeout
=
1001
;
int
newBatch
=
2001
;
Properties
properties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
initialTimeout
),
BATCH_PROPERTY
,
String
.
valueOf
(
initialBatch
));
SimpleConfig
config
=
prepareConfig
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
properties
);
AnnotationConfigApplicationContext
context
=
new
AnnotationConfigApplicationContext
(
AppConfig3
.
class
);
TestJavaConfigBean2
bean
=
context
.
getBean
(
TestJavaConfigBean2
.
class
);
assertEquals
(
initialTimeout
,
bean
.
getTimeout
());
assertEquals
(
initialBatch
,
bean
.
getBatch
());
Properties
newProperties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
newTimeout
),
BATCH_PROPERTY
,
String
.
valueOf
(
newBatch
));
config
.
onRepositoryChange
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
newProperties
);
TimeUnit
.
MILLISECONDS
.
sleep
(
50
);
// Does not support this scenario
assertEquals
(
initialTimeout
,
bean
.
getTimeout
());
assertEquals
(
initialBatch
,
bean
.
getBatch
());
}
@Test
public
void
testApplicationPropertySourceWithValueInjectedInConfiguration
()
throws
Exception
{
int
initialTimeout
=
1000
;
int
initialBatch
=
2000
;
int
newTimeout
=
1001
;
int
newBatch
=
2001
;
Properties
properties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
initialTimeout
),
BATCH_PROPERTY
,
String
.
valueOf
(
initialBatch
));
SimpleConfig
config
=
prepareConfig
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
properties
);
AnnotationConfigApplicationContext
context
=
new
AnnotationConfigApplicationContext
(
AppConfig7
.
class
);
TestJavaConfigBean2
bean
=
context
.
getBean
(
TestJavaConfigBean2
.
class
);
assertEquals
(
initialTimeout
,
bean
.
getTimeout
());
assertEquals
(
initialBatch
,
bean
.
getBatch
());
Properties
newProperties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
newTimeout
),
BATCH_PROPERTY
,
String
.
valueOf
(
newBatch
));
config
.
onRepositoryChange
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
newProperties
);
TimeUnit
.
MILLISECONDS
.
sleep
(
50
);
// Does not support this scenario
assertEquals
(
initialTimeout
,
bean
.
getTimeout
());
assertEquals
(
initialBatch
,
bean
.
getBatch
());
}
@Test
public
void
testAutoUpdateWithValueInjectedAsConstructorArgs
()
throws
Exception
{
int
initialTimeout
=
1000
;
int
initialBatch
=
2000
;
int
newTimeout
=
1001
;
int
newBatch
=
2001
;
Properties
properties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
initialTimeout
),
BATCH_PROPERTY
,
String
.
valueOf
(
initialBatch
));
SimpleConfig
config
=
prepareConfig
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
properties
);
AnnotationConfigApplicationContext
context
=
new
AnnotationConfigApplicationContext
(
AppConfig4
.
class
);
TestJavaConfigBean3
bean
=
context
.
getBean
(
TestJavaConfigBean3
.
class
);
assertEquals
(
initialTimeout
,
bean
.
getTimeout
());
assertEquals
(
initialBatch
,
bean
.
getBatch
());
Properties
newProperties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
newTimeout
),
BATCH_PROPERTY
,
String
.
valueOf
(
newBatch
));
config
.
onRepositoryChange
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
newProperties
);
TimeUnit
.
MILLISECONDS
.
sleep
(
50
);
// Does not support this scenario
assertEquals
(
initialTimeout
,
bean
.
getTimeout
());
assertEquals
(
initialBatch
,
bean
.
getBatch
());
}
@Test
public
void
testAutoUpdateWithInvalidSetter
()
throws
Exception
{
int
initialTimeout
=
1000
;
int
initialBatch
=
2000
;
int
newTimeout
=
1001
;
int
newBatch
=
2001
;
Properties
properties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
initialTimeout
),
BATCH_PROPERTY
,
String
.
valueOf
(
initialBatch
));
SimpleConfig
config
=
prepareConfig
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
properties
);
AnnotationConfigApplicationContext
context
=
new
AnnotationConfigApplicationContext
(
AppConfig5
.
class
);
TestJavaConfigBean4
bean
=
context
.
getBean
(
TestJavaConfigBean4
.
class
);
assertEquals
(
initialTimeout
,
bean
.
getTimeout
());
assertEquals
(
initialBatch
,
bean
.
getBatch
());
Properties
newProperties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
newTimeout
),
BATCH_PROPERTY
,
String
.
valueOf
(
newBatch
));
config
.
onRepositoryChange
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
newProperties
);
TimeUnit
.
MILLISECONDS
.
sleep
(
50
);
// Does not support this scenario
assertEquals
(
initialTimeout
,
bean
.
getTimeout
());
assertEquals
(
initialBatch
,
bean
.
getBatch
());
}
@Test
public
void
testAutoUpdateWithNestedProperty
()
throws
Exception
{
String
someKeyValue
=
"someKeyValue"
;
String
anotherKeyValue
=
"anotherKeyValue"
;
String
newKeyValue
=
"newKeyValue"
;
int
someValue
=
1234
;
int
someNewValue
=
2345
;
Properties
properties
=
assembleProperties
(
SOME_KEY_PROPERTY
,
someKeyValue
,
ANOTHER_KEY_PROPERTY
,
anotherKeyValue
,
String
.
format
(
"%s.%s"
,
someKeyValue
,
anotherKeyValue
),
String
.
valueOf
(
someValue
));
SimpleConfig
config
=
prepareConfig
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
properties
);
AnnotationConfigApplicationContext
context
=
new
AnnotationConfigApplicationContext
(
NestedPropertyConfig1
.
class
);
TestNestedPropertyBean
bean
=
context
.
getBean
(
TestNestedPropertyBean
.
class
);
assertEquals
(
someValue
,
bean
.
getNestedProperty
());
Properties
newProperties
=
assembleProperties
(
SOME_KEY_PROPERTY
,
newKeyValue
,
ANOTHER_KEY_PROPERTY
,
anotherKeyValue
,
String
.
format
(
"%s.%s"
,
newKeyValue
,
anotherKeyValue
),
String
.
valueOf
(
someNewValue
));
config
.
onRepositoryChange
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
newProperties
);
TimeUnit
.
MILLISECONDS
.
sleep
(
50
);
assertEquals
(
someNewValue
,
bean
.
getNestedProperty
());
}
@Test
public
void
testAutoUpdateWithNotSupportedNestedProperty
()
throws
Exception
{
String
someKeyValue
=
"someKeyValue"
;
String
anotherKeyValue
=
"anotherKeyValue"
;
int
someValue
=
1234
;
int
someNewValue
=
2345
;
Properties
properties
=
assembleProperties
(
SOME_KEY_PROPERTY
,
someKeyValue
,
ANOTHER_KEY_PROPERTY
,
anotherKeyValue
,
String
.
format
(
"%s.%s"
,
someKeyValue
,
anotherKeyValue
),
String
.
valueOf
(
someValue
));
SimpleConfig
config
=
prepareConfig
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
properties
);
AnnotationConfigApplicationContext
context
=
new
AnnotationConfigApplicationContext
(
NestedPropertyConfig1
.
class
);
TestNestedPropertyBean
bean
=
context
.
getBean
(
TestNestedPropertyBean
.
class
);
assertEquals
(
someValue
,
bean
.
getNestedProperty
());
Properties
newProperties
=
assembleProperties
(
SOME_KEY_PROPERTY
,
someKeyValue
,
ANOTHER_KEY_PROPERTY
,
anotherKeyValue
,
String
.
format
(
"%s.%s"
,
someKeyValue
,
anotherKeyValue
),
String
.
valueOf
(
someNewValue
));
config
.
onRepositoryChange
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
newProperties
);
TimeUnit
.
MILLISECONDS
.
sleep
(
50
);
// Does not support this scenario
assertEquals
(
someValue
,
bean
.
getNestedProperty
());
}
@Test
public
void
testAutoUpdateWithNestedPropertyWithDefaultValue
()
throws
Exception
{
String
someKeyValue
=
"someKeyValue"
;
String
someNewKeyValue
=
"someNewKeyValue"
;
int
someValue
=
1234
;
int
someNewValue
=
2345
;
Properties
properties
=
assembleProperties
(
SOME_KEY_PROPERTY
,
someKeyValue
,
ANOTHER_KEY_PROPERTY
,
String
.
valueOf
(
someValue
));
SimpleConfig
config
=
prepareConfig
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
properties
);
AnnotationConfigApplicationContext
context
=
new
AnnotationConfigApplicationContext
(
NestedPropertyConfig2
.
class
);
TestNestedPropertyBeanWithDefaultValue
bean
=
context
.
getBean
(
TestNestedPropertyBeanWithDefaultValue
.
class
);
assertEquals
(
someValue
,
bean
.
getNestedProperty
());
Properties
newProperties
=
assembleProperties
(
SOME_KEY_PROPERTY
,
someNewKeyValue
,
ANOTHER_KEY_PROPERTY
,
String
.
valueOf
(
someValue
),
someNewKeyValue
,
String
.
valueOf
(
someNewValue
));
config
.
onRepositoryChange
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
newProperties
);
TimeUnit
.
MILLISECONDS
.
sleep
(
50
);
assertEquals
(
someNewValue
,
bean
.
getNestedProperty
());
}
@Test
public
void
testAutoUpdateWithMultipleNestedProperty
()
throws
Exception
{
String
someKeyValue
=
"someKeyValue"
;
String
someNewKeyValue
=
"someNewKeyValue"
;
String
anotherKeyValue
=
"anotherKeyValue"
;
String
someNestedKey
=
"someNestedKey"
;
String
someNestedPlaceholder
=
String
.
format
(
"${%s}"
,
someNestedKey
);
String
anotherNestedKey
=
"anotherNestedKey"
;
String
anotherNestedPlaceholder
=
String
.
format
(
"${%s}"
,
anotherNestedKey
);
int
someValue
=
1234
;
int
someNewValue
=
2345
;
Properties
properties
=
assembleProperties
(
SOME_KEY_PROPERTY
,
someKeyValue
,
ANOTHER_KEY_PROPERTY
,
anotherKeyValue
,
someKeyValue
,
someNestedPlaceholder
);
properties
.
setProperty
(
someNestedKey
,
String
.
valueOf
(
someValue
));
SimpleConfig
config
=
prepareConfig
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
properties
);
AnnotationConfigApplicationContext
context
=
new
AnnotationConfigApplicationContext
(
NestedPropertyConfig2
.
class
);
TestNestedPropertyBeanWithDefaultValue
bean
=
context
.
getBean
(
TestNestedPropertyBeanWithDefaultValue
.
class
);
assertEquals
(
someValue
,
bean
.
getNestedProperty
());
Properties
newProperties
=
assembleProperties
(
SOME_KEY_PROPERTY
,
someNewKeyValue
,
ANOTHER_KEY_PROPERTY
,
anotherKeyValue
,
someNewKeyValue
,
anotherNestedPlaceholder
);
newProperties
.
setProperty
(
anotherNestedKey
,
String
.
valueOf
(
someNewValue
));
config
.
onRepositoryChange
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
newProperties
);
TimeUnit
.
MILLISECONDS
.
sleep
(
50
);
assertEquals
(
someNewValue
,
bean
.
getNestedProperty
());
}
@Test
public
void
testAutoUpdateWithAllKindsOfDataTypes
()
throws
Exception
{
int
someInt
=
1000
;
int
someNewInt
=
1001
;
int
[]
someIntArray
=
{
1
,
2
,
3
,
4
};
int
[]
someNewIntArray
=
{
5
,
6
,
7
,
8
};
long
someLong
=
2000L
;
long
someNewLong
=
2001L
;
short
someShort
=
3000
;
short
someNewShort
=
3001
;
float
someFloat
=
1.2
F
;
float
someNewFloat
=
2.2
F
;
double
someDouble
=
3.10
D
;
double
someNewDouble
=
4.10
D
;
byte
someByte
=
123
;
byte
someNewByte
=
124
;
boolean
someBoolean
=
true
;
boolean
someNewBoolean
=
!
someBoolean
;
String
someString
=
"someString"
;
String
someNewString
=
"someNewString"
;
String
someDateFormat
=
"yyyy-MM-dd HH:mm:ss.SSS"
;
Date
someDate
=
assembleDate
(
2018
,
2
,
23
,
20
,
1
,
2
,
123
);
Date
someNewDate
=
assembleDate
(
2018
,
2
,
23
,
21
,
2
,
3
,
345
);
SimpleDateFormat
simpleDateFormat
=
new
SimpleDateFormat
(
someDateFormat
,
Locale
.
US
);
Properties
properties
=
new
Properties
();
properties
.
setProperty
(
"intProperty"
,
String
.
valueOf
(
someInt
));
properties
.
setProperty
(
"intArrayProperty"
,
Ints
.
join
(
", "
,
someIntArray
));
properties
.
setProperty
(
"longProperty"
,
String
.
valueOf
(
someLong
));
properties
.
setProperty
(
"shortProperty"
,
String
.
valueOf
(
someShort
));
properties
.
setProperty
(
"floatProperty"
,
String
.
valueOf
(
someFloat
));
properties
.
setProperty
(
"doubleProperty"
,
String
.
valueOf
(
someDouble
));
properties
.
setProperty
(
"byteProperty"
,
String
.
valueOf
(
someByte
));
properties
.
setProperty
(
"booleanProperty"
,
String
.
valueOf
(
someBoolean
));
properties
.
setProperty
(
"stringProperty"
,
String
.
valueOf
(
someString
));
properties
.
setProperty
(
"dateFormat"
,
String
.
valueOf
(
someDateFormat
));
properties
.
setProperty
(
"dateProperty"
,
simpleDateFormat
.
format
(
someDate
));
SimpleConfig
config
=
prepareConfig
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
properties
);
AnnotationConfigApplicationContext
context
=
new
AnnotationConfigApplicationContext
(
AppConfig9
.
class
);
TestAllKindsOfDataTypesBean
bean
=
context
.
getBean
(
TestAllKindsOfDataTypesBean
.
class
);
assertEquals
(
someInt
,
bean
.
getIntProperty
());
assertArrayEquals
(
someIntArray
,
bean
.
getIntArrayProperty
());
assertEquals
(
someLong
,
bean
.
getLongProperty
());
assertEquals
(
someShort
,
bean
.
getShortProperty
());
assertEquals
(
someFloat
,
bean
.
getFloatProperty
(),
0.001
F
);
assertEquals
(
someDouble
,
bean
.
getDoubleProperty
(),
0.001
D
);
assertEquals
(
someByte
,
bean
.
getByteProperty
());
assertEquals
(
someBoolean
,
bean
.
getBooleanProperty
());
assertEquals
(
someString
,
bean
.
getStringProperty
());
assertEquals
(
someDate
,
bean
.
getDateProperty
());
Properties
newProperties
=
new
Properties
();
newProperties
.
setProperty
(
"intProperty"
,
String
.
valueOf
(
someNewInt
));
newProperties
.
setProperty
(
"intArrayProperty"
,
Ints
.
join
(
", "
,
someNewIntArray
));
newProperties
.
setProperty
(
"longProperty"
,
String
.
valueOf
(
someNewLong
));
newProperties
.
setProperty
(
"shortProperty"
,
String
.
valueOf
(
someNewShort
));
newProperties
.
setProperty
(
"floatProperty"
,
String
.
valueOf
(
someNewFloat
));
newProperties
.
setProperty
(
"doubleProperty"
,
String
.
valueOf
(
someNewDouble
));
newProperties
.
setProperty
(
"byteProperty"
,
String
.
valueOf
(
someNewByte
));
newProperties
.
setProperty
(
"booleanProperty"
,
String
.
valueOf
(
someNewBoolean
));
newProperties
.
setProperty
(
"stringProperty"
,
String
.
valueOf
(
someNewString
));
newProperties
.
setProperty
(
"dateFormat"
,
String
.
valueOf
(
someDateFormat
));
newProperties
.
setProperty
(
"dateProperty"
,
simpleDateFormat
.
format
(
someNewDate
));
config
.
onRepositoryChange
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
newProperties
);
TimeUnit
.
MILLISECONDS
.
sleep
(
50
);
assertEquals
(
someNewInt
,
bean
.
getIntProperty
());
assertArrayEquals
(
someNewIntArray
,
bean
.
getIntArrayProperty
());
assertEquals
(
someNewLong
,
bean
.
getLongProperty
());
assertEquals
(
someNewShort
,
bean
.
getShortProperty
());
assertEquals
(
someNewFloat
,
bean
.
getFloatProperty
(),
0.001
F
);
assertEquals
(
someNewDouble
,
bean
.
getDoubleProperty
(),
0.001
D
);
assertEquals
(
someNewByte
,
bean
.
getByteProperty
());
assertEquals
(
someNewBoolean
,
bean
.
getBooleanProperty
());
assertEquals
(
someNewString
,
bean
.
getStringProperty
());
assertEquals
(
someNewDate
,
bean
.
getDateProperty
());
}
@Configuration
@EnableApolloConfig
static
class
AppConfig1
{
@Bean
TestJavaConfigBean
testJavaConfigBean
()
{
return
new
TestJavaConfigBean
();
}
}
@Configuration
@EnableApolloConfig
({
"application"
,
"FX.apollo"
})
static
class
AppConfig2
{
@Bean
TestJavaConfigBean
testJavaConfigBean
()
{
return
new
TestJavaConfigBean
();
}
}
@Configuration
@EnableApolloConfig
static
class
AppConfig3
{
/**
* This case won't get auto updated
*/
@Bean
TestJavaConfigBean2
testJavaConfigBean2
(
@Value
(
"${timeout:100}"
)
int
timeout
,
@Value
(
"${batch:200}"
)
int
batch
)
{
TestJavaConfigBean2
bean
=
new
TestJavaConfigBean2
();
bean
.
setTimeout
(
timeout
);
bean
.
setBatch
(
batch
);
return
bean
;
}
}
@Configuration
@ComponentScan
(
includeFilters
=
{
@Filter
(
type
=
FilterType
.
ANNOTATION
,
value
=
{
Component
.
class
})},
excludeFilters
=
{
@Filter
(
type
=
FilterType
.
ANNOTATION
,
value
=
{
Configuration
.
class
})})
@EnableApolloConfig
static
class
AppConfig4
{
}
@Configuration
@EnableApolloConfig
static
class
AppConfig5
{
@Bean
TestJavaConfigBean4
testJavaConfigBean
()
{
return
new
TestJavaConfigBean4
();
}
}
@Configuration
@EnableApolloConfig
static
class
AppConfig6
{
@Bean
TestJavaConfigBean5
testJavaConfigBean
()
{
return
new
TestJavaConfigBean5
();
}
}
@Configuration
@EnableApolloConfig
static
class
AppConfig7
{
@Value
(
"${batch}"
)
private
int
batch
;
@Bean
@Value
(
"${timeout}"
)
TestJavaConfigBean2
testJavaConfigBean2
(
int
timeout
)
{
TestJavaConfigBean2
bean
=
new
TestJavaConfigBean2
();
bean
.
setTimeout
(
timeout
);
bean
.
setBatch
(
batch
);
return
bean
;
}
}
@Configuration
@EnableApolloConfig
@ImportResource
(
"spring/XmlConfigPlaceholderTest1.xml"
)
static
class
AppConfig8
{
@Bean
TestJavaConfigBean
testJavaConfigBean
()
{
return
new
TestJavaConfigBean
();
}
}
@Configuration
@EnableApolloConfig
static
class
AppConfig9
{
@Bean
TestAllKindsOfDataTypesBean
testAllKindsOfDataTypesBean
()
{
return
new
TestAllKindsOfDataTypesBean
();
}
}
@Configuration
@EnableApolloConfig
static
class
NestedPropertyConfig1
{
@Bean
TestNestedPropertyBean
testNestedPropertyBean
()
{
return
new
TestNestedPropertyBean
();
}
}
@Configuration
@EnableApolloConfig
static
class
NestedPropertyConfig2
{
@Bean
TestNestedPropertyBeanWithDefaultValue
testNestedPropertyBean
()
{
return
new
TestNestedPropertyBeanWithDefaultValue
();
}
}
static
class
TestJavaConfigBean
{
@Value
(
"${timeout:100}"
)
private
int
timeout
;
private
int
batch
;
@Value
(
"${batch:200}"
)
public
void
setBatch
(
int
batch
)
{
this
.
batch
=
batch
;
}
public
int
getTimeout
()
{
return
timeout
;
}
public
int
getBatch
()
{
return
batch
;
}
}
static
class
TestJavaConfigBean2
{
private
int
timeout
;
private
int
batch
;
public
int
getTimeout
()
{
return
timeout
;
}
public
void
setTimeout
(
int
timeout
)
{
this
.
timeout
=
timeout
;
}
public
int
getBatch
()
{
return
batch
;
}
public
void
setBatch
(
int
batch
)
{
this
.
batch
=
batch
;
}
}
/**
* This case won't get auto updated
*/
@Component
static
class
TestJavaConfigBean3
{
private
final
int
timeout
;
private
final
int
batch
;
@Autowired
public
TestJavaConfigBean3
(
@Value
(
"${timeout:100}"
)
int
timeout
,
@Value
(
"${batch:200}"
)
int
batch
)
{
this
.
timeout
=
timeout
;
this
.
batch
=
batch
;
}
public
int
getTimeout
()
{
return
timeout
;
}
public
int
getBatch
()
{
return
batch
;
}
}
/**
* This case won't get auto updated
*/
static
class
TestJavaConfigBean4
{
private
int
timeout
;
private
int
batch
;
@Value
(
"${batch:200}"
)
public
void
setValues
(
int
batch
,
@Value
(
"${timeout:100}"
)
int
timeout
)
{
this
.
batch
=
batch
;
this
.
timeout
=
timeout
;
}
public
int
getTimeout
()
{
return
timeout
;
}
public
int
getBatch
()
{
return
batch
;
}
}
static
class
TestJavaConfigBean5
{
@Value
(
"${timeout}"
)
private
int
timeout
;
private
int
batch
;
@Value
(
"${batch}"
)
public
void
setBatch
(
int
batch
)
{
this
.
batch
=
batch
;
}
public
int
getTimeout
()
{
return
timeout
;
}
public
int
getBatch
()
{
return
batch
;
}
}
static
class
TestNestedPropertyBean
{
@Value
(
"${${someKey}.${anotherKey}}"
)
private
int
nestedProperty
;
public
int
getNestedProperty
()
{
return
nestedProperty
;
}
}
static
class
TestNestedPropertyBeanWithDefaultValue
{
@Value
(
"${${someKey}:${anotherKey}}"
)
private
int
nestedProperty
;
public
int
getNestedProperty
()
{
return
nestedProperty
;
}
}
static
class
TestAllKindsOfDataTypesBean
{
@Value
(
"${intProperty}"
)
private
int
intProperty
;
@Value
(
"${intArrayProperty}"
)
private
int
[]
intArrayProperty
;
@Value
(
"${longProperty}"
)
private
long
longProperty
;
@Value
(
"${shortProperty}"
)
private
short
shortProperty
;
@Value
(
"${floatProperty}"
)
private
float
floatProperty
;
@Value
(
"${doubleProperty}"
)
private
double
doubleProperty
;
@Value
(
"${byteProperty}"
)
private
byte
byteProperty
;
@Value
(
"${booleanProperty}"
)
private
boolean
booleanProperty
;
@Value
(
"${stringProperty}"
)
private
String
stringProperty
;
@Value
(
"#{new java.text.SimpleDateFormat('${dateFormat}').parse('${dateProperty}')}"
)
private
Date
dateProperty
;
public
int
getIntProperty
()
{
return
intProperty
;
}
public
int
[]
getIntArrayProperty
()
{
return
intArrayProperty
;
}
public
long
getLongProperty
()
{
return
longProperty
;
}
public
short
getShortProperty
()
{
return
shortProperty
;
}
public
float
getFloatProperty
()
{
return
floatProperty
;
}
public
double
getDoubleProperty
()
{
return
doubleProperty
;
}
public
byte
getByteProperty
()
{
return
byteProperty
;
}
public
boolean
getBooleanProperty
()
{
return
booleanProperty
;
}
public
String
getStringProperty
()
{
return
stringProperty
;
}
public
Date
getDateProperty
()
{
return
dateProperty
;
}
}
}
apollo-client/src/test/java/com/ctrip/framework/apollo/spring/JavaConfigPlaceholderTest.java
View file @
5823daa6
...
@@ -7,15 +7,19 @@ import static org.mockito.Mockito.mock;
...
@@ -7,15 +7,19 @@ import static org.mockito.Mockito.mock;
import
static
org
.
mockito
.
Mockito
.
when
;
import
static
org
.
mockito
.
Mockito
.
when
;
import
org.junit.Test
;
import
org.junit.Test
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.context.annotation.AnnotationConfigApplicationContext
;
import
org.springframework.context.annotation.AnnotationConfigApplicationContext
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.Bean
;
import
org.springframework.context.annotation.ComponentScan
;
import
org.springframework.context.annotation.ComponentScan.Filter
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.stereotype.Component
;
import
com.ctrip.framework.apollo.Config
;
import
com.ctrip.framework.apollo.Config
;
import
com.ctrip.framework.apollo.core.ConfigConsts
;
import
com.ctrip.framework.apollo.core.ConfigConsts
;
import
com.ctrip.framework.apollo.spring.annotation.EnableApolloConfig
;
import
com.ctrip.framework.apollo.spring.annotation.EnableApolloConfig
;
import
org.springframework.context.annotation.FilterType
;
import
org.springframework.stereotype.Component
;
/**
/**
* @author Jason Song(song_s@ctrip.com)
* @author Jason Song(song_s@ctrip.com)
...
@@ -153,6 +157,25 @@ public class JavaConfigPlaceholderTest extends AbstractSpringIntegrationTest {
...
@@ -153,6 +157,25 @@ public class JavaConfigPlaceholderTest extends AbstractSpringIntegrationTest {
assertEquals
(
someBatch
,
bean
.
getBatch
());
assertEquals
(
someBatch
,
bean
.
getBatch
());
}
}
@Test
public
void
testApplicationPropertySourceWithValueInjectedAsConstructorArgs
()
throws
Exception
{
int
someTimeout
=
1000
;
int
someBatch
=
2000
;
Config
config
=
mock
(
Config
.
class
);
when
(
config
.
getProperty
(
eq
(
TIMEOUT_PROPERTY
),
anyString
())).
thenReturn
(
String
.
valueOf
(
someTimeout
));
when
(
config
.
getProperty
(
eq
(
BATCH_PROPERTY
),
anyString
())).
thenReturn
(
String
.
valueOf
(
someBatch
));
mockConfig
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
config
);
AnnotationConfigApplicationContext
context
=
new
AnnotationConfigApplicationContext
(
AppConfig7
.
class
);
TestJavaConfigBean3
bean
=
context
.
getBean
(
TestJavaConfigBean3
.
class
);
assertEquals
(
someTimeout
,
bean
.
getTimeout
());
assertEquals
(
someBatch
,
bean
.
getBatch
());
}
@Test
@Test
public
void
testNestedProperty
()
throws
Exception
{
public
void
testNestedProperty
()
throws
Exception
{
String
a
=
"a"
;
String
a
=
"a"
;
...
@@ -323,6 +346,14 @@ public class JavaConfigPlaceholderTest extends AbstractSpringIntegrationTest {
...
@@ -323,6 +346,14 @@ public class JavaConfigPlaceholderTest extends AbstractSpringIntegrationTest {
}
}
}
}
@Configuration
@ComponentScan
(
includeFilters
=
{
@Filter
(
type
=
FilterType
.
ANNOTATION
,
value
=
{
Component
.
class
})},
excludeFilters
=
{
@Filter
(
type
=
FilterType
.
ANNOTATION
,
value
=
{
Configuration
.
class
})})
@EnableApolloConfig
static
class
AppConfig7
{
}
@Configuration
@Configuration
@EnableApolloConfig
@EnableApolloConfig
static
class
NestedPropertyConfig1
{
static
class
NestedPropertyConfig1
{
...
@@ -332,8 +363,6 @@ public class JavaConfigPlaceholderTest extends AbstractSpringIntegrationTest {
...
@@ -332,8 +363,6 @@ public class JavaConfigPlaceholderTest extends AbstractSpringIntegrationTest {
}
}
}
}
@Component
static
class
TestJavaConfigBean
{
static
class
TestJavaConfigBean
{
@Value
(
"${timeout:100}"
)
@Value
(
"${timeout:100}"
)
private
int
timeout
;
private
int
timeout
;
...
@@ -374,6 +403,27 @@ public class JavaConfigPlaceholderTest extends AbstractSpringIntegrationTest {
...
@@ -374,6 +403,27 @@ public class JavaConfigPlaceholderTest extends AbstractSpringIntegrationTest {
}
}
}
}
@Component
static
class
TestJavaConfigBean3
{
private
final
int
timeout
;
private
final
int
batch
;
@Autowired
public
TestJavaConfigBean3
(
@Value
(
"${timeout:100}"
)
int
timeout
,
@Value
(
"${batch:200}"
)
int
batch
)
{
this
.
timeout
=
timeout
;
this
.
batch
=
batch
;
}
public
int
getTimeout
()
{
return
timeout
;
}
public
int
getBatch
()
{
return
batch
;
}
}
static
class
TestNestedPropertyBean
{
static
class
TestNestedPropertyBean
{
@Value
(
"${${a}.${b}:${c:100}}"
)
@Value
(
"${${a}.${b}:${c:100}}"
)
...
...
apollo-client/src/test/java/com/ctrip/framework/apollo/spring/XMLConfigAnnotationTest.java
View file @
5823daa6
...
@@ -86,7 +86,8 @@ public class XMLConfigAnnotationTest extends AbstractSpringIntegrationTest {
...
@@ -86,7 +86,8 @@ public class XMLConfigAnnotationTest extends AbstractSpringIntegrationTest {
TestApolloConfigChangeListenerBean1
bean
=
getBean
(
"spring/XmlConfigAnnotationTest3.xml"
,
TestApolloConfigChangeListenerBean1
bean
=
getBean
(
"spring/XmlConfigAnnotationTest3.xml"
,
TestApolloConfigChangeListenerBean1
.
class
);
TestApolloConfigChangeListenerBean1
.
class
);
assertEquals
(
3
,
applicationListeners
.
size
());
//PropertySourcesProcessor add listeners to listen config changed of all namespace
assertEquals
(
4
,
applicationListeners
.
size
());
assertEquals
(
1
,
fxApolloListeners
.
size
());
assertEquals
(
1
,
fxApolloListeners
.
size
());
for
(
ConfigChangeListener
listener
:
applicationListeners
)
{
for
(
ConfigChangeListener
listener
:
applicationListeners
)
{
...
...
apollo-client/src/test/java/com/ctrip/framework/apollo/spring/XmlConfigPlaceholderAutoUpdateTest.java
0 → 100644
View file @
5823daa6
package
com
.
ctrip
.
framework
.
apollo
.
spring
;
import
static
org
.
junit
.
Assert
.
assertArrayEquals
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
com.ctrip.framework.apollo.build.MockInjector
;
import
com.ctrip.framework.apollo.core.ConfigConsts
;
import
com.ctrip.framework.apollo.internals.SimpleConfig
;
import
com.ctrip.framework.apollo.spring.XmlConfigPlaceholderTest.TestXmlBean
;
import
com.ctrip.framework.apollo.util.ConfigUtil
;
import
com.google.common.primitives.Ints
;
import
java.text.SimpleDateFormat
;
import
java.util.Date
;
import
java.util.Locale
;
import
java.util.Properties
;
import
java.util.concurrent.TimeUnit
;
import
org.junit.Test
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.context.support.ClassPathXmlApplicationContext
;
public
class
XmlConfigPlaceholderAutoUpdateTest
extends
AbstractSpringIntegrationTest
{
private
static
final
String
TIMEOUT_PROPERTY
=
"timeout"
;
private
static
final
int
DEFAULT_TIMEOUT
=
100
;
private
static
final
String
BATCH_PROPERTY
=
"batch"
;
private
static
final
int
DEFAULT_BATCH
=
200
;
private
static
final
String
FX_APOLLO_NAMESPACE
=
"FX.apollo"
;
@Test
public
void
testAutoUpdateWithOneNamespace
()
throws
Exception
{
int
initialTimeout
=
1000
;
int
initialBatch
=
2000
;
int
newTimeout
=
1001
;
int
newBatch
=
2001
;
Properties
properties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
initialTimeout
),
BATCH_PROPERTY
,
String
.
valueOf
(
initialBatch
));
SimpleConfig
config
=
prepareConfig
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
properties
);
ClassPathXmlApplicationContext
context
=
new
ClassPathXmlApplicationContext
(
"spring/XmlConfigPlaceholderTest1.xml"
);
TestXmlBean
bean
=
context
.
getBean
(
TestXmlBean
.
class
);
assertEquals
(
initialTimeout
,
bean
.
getTimeout
());
assertEquals
(
initialBatch
,
bean
.
getBatch
());
Properties
newProperties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
newTimeout
),
BATCH_PROPERTY
,
String
.
valueOf
(
newBatch
));
config
.
onRepositoryChange
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
newProperties
);
TimeUnit
.
MILLISECONDS
.
sleep
(
50
);
assertEquals
(
newTimeout
,
bean
.
getTimeout
());
assertEquals
(
newBatch
,
bean
.
getBatch
());
}
@Test
public
void
testAutoUpdateDisabled
()
throws
Exception
{
int
initialTimeout
=
1000
;
int
initialBatch
=
2000
;
int
newTimeout
=
1001
;
int
newBatch
=
2001
;
MockConfigUtil
mockConfigUtil
=
new
MockConfigUtil
();
mockConfigUtil
.
setAutoUpdateInjectedSpringProperties
(
false
);
MockInjector
.
setInstance
(
ConfigUtil
.
class
,
mockConfigUtil
);
Properties
properties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
initialTimeout
),
BATCH_PROPERTY
,
String
.
valueOf
(
initialBatch
));
SimpleConfig
config
=
prepareConfig
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
properties
);
ClassPathXmlApplicationContext
context
=
new
ClassPathXmlApplicationContext
(
"spring/XmlConfigPlaceholderTest1.xml"
);
TestXmlBean
bean
=
context
.
getBean
(
TestXmlBean
.
class
);
assertEquals
(
initialTimeout
,
bean
.
getTimeout
());
assertEquals
(
initialBatch
,
bean
.
getBatch
());
Properties
newProperties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
newTimeout
),
BATCH_PROPERTY
,
String
.
valueOf
(
newBatch
));
config
.
onRepositoryChange
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
newProperties
);
TimeUnit
.
MILLISECONDS
.
sleep
(
50
);
assertEquals
(
initialTimeout
,
bean
.
getTimeout
());
assertEquals
(
initialBatch
,
bean
.
getBatch
());
}
@Test
public
void
testAutoUpdateWithMultipleNamespaces
()
throws
Exception
{
int
initialTimeout
=
1000
;
int
initialBatch
=
2000
;
int
newTimeout
=
1001
;
int
newBatch
=
2001
;
Properties
applicationProperties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
initialTimeout
));
Properties
fxApolloProperties
=
assembleProperties
(
BATCH_PROPERTY
,
String
.
valueOf
(
initialBatch
));
SimpleConfig
applicationConfig
=
prepareConfig
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
applicationProperties
);
SimpleConfig
fxApolloConfig
=
prepareConfig
(
FX_APOLLO_NAMESPACE
,
fxApolloProperties
);
ClassPathXmlApplicationContext
context
=
new
ClassPathXmlApplicationContext
(
"spring/XmlConfigPlaceholderTest3.xml"
);
TestXmlBean
bean
=
context
.
getBean
(
TestXmlBean
.
class
);
assertEquals
(
initialTimeout
,
bean
.
getTimeout
());
assertEquals
(
initialBatch
,
bean
.
getBatch
());
Properties
newApplicationProperties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
newTimeout
));
applicationConfig
.
onRepositoryChange
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
newApplicationProperties
);
TimeUnit
.
MILLISECONDS
.
sleep
(
50
);
assertEquals
(
newTimeout
,
bean
.
getTimeout
());
assertEquals
(
initialBatch
,
bean
.
getBatch
());
Properties
newFxApolloProperties
=
assembleProperties
(
BATCH_PROPERTY
,
String
.
valueOf
(
newBatch
));
fxApolloConfig
.
onRepositoryChange
(
FX_APOLLO_NAMESPACE
,
newFxApolloProperties
);
TimeUnit
.
MILLISECONDS
.
sleep
(
50
);
assertEquals
(
newTimeout
,
bean
.
getTimeout
());
assertEquals
(
newBatch
,
bean
.
getBatch
());
}
@Test
public
void
testAutoUpdateWithMultipleNamespacesWithSameProperties
()
throws
Exception
{
int
someTimeout
=
1000
;
int
someBatch
=
2000
;
int
anotherBatch
=
3000
;
int
someNewTimeout
=
1001
;
int
someNewBatch
=
2001
;
Properties
applicationProperties
=
assembleProperties
(
BATCH_PROPERTY
,
String
.
valueOf
(
someBatch
));
Properties
fxApolloProperties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
someTimeout
),
BATCH_PROPERTY
,
String
.
valueOf
(
anotherBatch
));
SimpleConfig
applicationConfig
=
prepareConfig
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
applicationProperties
);
SimpleConfig
fxApolloConfig
=
prepareConfig
(
FX_APOLLO_NAMESPACE
,
fxApolloProperties
);
ClassPathXmlApplicationContext
context
=
new
ClassPathXmlApplicationContext
(
"spring/XmlConfigPlaceholderTest3.xml"
);
TestXmlBean
bean
=
context
.
getBean
(
TestXmlBean
.
class
);
assertEquals
(
someTimeout
,
bean
.
getTimeout
());
assertEquals
(
someBatch
,
bean
.
getBatch
());
Properties
newFxApolloProperties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
someNewTimeout
),
BATCH_PROPERTY
,
String
.
valueOf
(
someNewBatch
));
fxApolloConfig
.
onRepositoryChange
(
FX_APOLLO_NAMESPACE
,
newFxApolloProperties
);
TimeUnit
.
MILLISECONDS
.
sleep
(
50
);
assertEquals
(
someNewTimeout
,
bean
.
getTimeout
());
assertEquals
(
someBatch
,
bean
.
getBatch
());
}
@Test
public
void
testAutoUpdateWithNewProperties
()
throws
Exception
{
int
initialTimeout
=
1000
;
int
newTimeout
=
1001
;
int
newBatch
=
2001
;
Properties
applicationProperties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
initialTimeout
));
SimpleConfig
applicationConfig
=
prepareConfig
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
applicationProperties
);
ClassPathXmlApplicationContext
context
=
new
ClassPathXmlApplicationContext
(
"spring/XmlConfigPlaceholderTest1.xml"
);
TestXmlBean
bean
=
context
.
getBean
(
TestXmlBean
.
class
);
assertEquals
(
initialTimeout
,
bean
.
getTimeout
());
assertEquals
(
DEFAULT_BATCH
,
bean
.
getBatch
());
Properties
newApplicationProperties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
newTimeout
),
BATCH_PROPERTY
,
String
.
valueOf
(
newBatch
));
applicationConfig
.
onRepositoryChange
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
newApplicationProperties
);
TimeUnit
.
MILLISECONDS
.
sleep
(
50
);
assertEquals
(
newTimeout
,
bean
.
getTimeout
());
assertEquals
(
newBatch
,
bean
.
getBatch
());
}
@Test
public
void
testAutoUpdateWithIrrelevantProperties
()
throws
Exception
{
int
initialTimeout
=
1000
;
String
someIrrelevantKey
=
"someIrrelevantKey"
;
String
someIrrelevantValue
=
"someIrrelevantValue"
;
String
anotherIrrelevantKey
=
"anotherIrrelevantKey"
;
String
anotherIrrelevantValue
=
"anotherIrrelevantValue"
;
Properties
applicationProperties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
initialTimeout
),
someIrrelevantKey
,
someIrrelevantValue
);
SimpleConfig
applicationConfig
=
prepareConfig
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
applicationProperties
);
ClassPathXmlApplicationContext
context
=
new
ClassPathXmlApplicationContext
(
"spring/XmlConfigPlaceholderTest1.xml"
);
TestXmlBean
bean
=
context
.
getBean
(
TestXmlBean
.
class
);
assertEquals
(
initialTimeout
,
bean
.
getTimeout
());
assertEquals
(
DEFAULT_BATCH
,
bean
.
getBatch
());
Properties
newApplicationProperties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
initialTimeout
),
anotherIrrelevantKey
,
String
.
valueOf
(
anotherIrrelevantValue
));
applicationConfig
.
onRepositoryChange
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
newApplicationProperties
);
TimeUnit
.
MILLISECONDS
.
sleep
(
50
);
assertEquals
(
initialTimeout
,
bean
.
getTimeout
());
assertEquals
(
DEFAULT_BATCH
,
bean
.
getBatch
());
}
@Test
public
void
testAutoUpdateWithDeletedProperties
()
throws
Exception
{
int
initialTimeout
=
1000
;
int
initialBatch
=
2000
;
Properties
properties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
initialTimeout
),
BATCH_PROPERTY
,
String
.
valueOf
(
initialBatch
));
SimpleConfig
config
=
prepareConfig
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
properties
);
ClassPathXmlApplicationContext
context
=
new
ClassPathXmlApplicationContext
(
"spring/XmlConfigPlaceholderTest1.xml"
);
TestXmlBean
bean
=
context
.
getBean
(
TestXmlBean
.
class
);
assertEquals
(
initialTimeout
,
bean
.
getTimeout
());
assertEquals
(
initialBatch
,
bean
.
getBatch
());
Properties
newProperties
=
new
Properties
();
config
.
onRepositoryChange
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
newProperties
);
TimeUnit
.
MILLISECONDS
.
sleep
(
50
);
assertEquals
(
DEFAULT_TIMEOUT
,
bean
.
getTimeout
());
assertEquals
(
DEFAULT_BATCH
,
bean
.
getBatch
());
}
@Test
public
void
testAutoUpdateWithDeletedPropertiesWithNoDefaultValue
()
throws
Exception
{
int
initialTimeout
=
1000
;
int
initialBatch
=
2000
;
int
newTimeout
=
1001
;
Properties
properties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
initialTimeout
),
BATCH_PROPERTY
,
String
.
valueOf
(
initialBatch
));
SimpleConfig
config
=
prepareConfig
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
properties
);
ClassPathXmlApplicationContext
context
=
new
ClassPathXmlApplicationContext
(
"spring/XmlConfigPlaceholderTest7.xml"
);
TestXmlBean
bean
=
context
.
getBean
(
TestXmlBean
.
class
);
assertEquals
(
initialTimeout
,
bean
.
getTimeout
());
assertEquals
(
initialBatch
,
bean
.
getBatch
());
Properties
newProperties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
newTimeout
));
config
.
onRepositoryChange
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
newProperties
);
TimeUnit
.
MILLISECONDS
.
sleep
(
50
);
assertEquals
(
newTimeout
,
bean
.
getTimeout
());
assertEquals
(
initialBatch
,
bean
.
getBatch
());
}
@Test
public
void
testAutoUpdateWithTypeMismatch
()
throws
Exception
{
int
initialTimeout
=
1000
;
int
initialBatch
=
2000
;
int
newTimeout
=
1001
;
String
newBatch
=
"newBatch"
;
Properties
properties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
initialTimeout
),
BATCH_PROPERTY
,
String
.
valueOf
(
initialBatch
));
SimpleConfig
config
=
prepareConfig
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
properties
);
ClassPathXmlApplicationContext
context
=
new
ClassPathXmlApplicationContext
(
"spring/XmlConfigPlaceholderTest1.xml"
);
TestXmlBean
bean
=
context
.
getBean
(
TestXmlBean
.
class
);
assertEquals
(
initialTimeout
,
bean
.
getTimeout
());
assertEquals
(
initialBatch
,
bean
.
getBatch
());
Properties
newProperties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
newTimeout
),
BATCH_PROPERTY
,
newBatch
);
config
.
onRepositoryChange
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
newProperties
);
TimeUnit
.
MILLISECONDS
.
sleep
(
50
);
assertEquals
(
newTimeout
,
bean
.
getTimeout
());
assertEquals
(
initialBatch
,
bean
.
getBatch
());
}
@Test
public
void
testAutoUpdateWithValueInjectedAsConstructorArgs
()
throws
Exception
{
int
initialTimeout
=
1000
;
int
initialBatch
=
2000
;
int
newTimeout
=
1001
;
int
newBatch
=
2001
;
Properties
properties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
initialTimeout
),
BATCH_PROPERTY
,
String
.
valueOf
(
initialBatch
));
SimpleConfig
config
=
prepareConfig
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
properties
);
ClassPathXmlApplicationContext
context
=
new
ClassPathXmlApplicationContext
(
"spring/XmlConfigPlaceholderTest8.xml"
);
TestXmlBeanWithConstructorArgs
bean
=
context
.
getBean
(
TestXmlBeanWithConstructorArgs
.
class
);
assertEquals
(
initialTimeout
,
bean
.
getTimeout
());
assertEquals
(
initialBatch
,
bean
.
getBatch
());
Properties
newProperties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
newTimeout
),
BATCH_PROPERTY
,
String
.
valueOf
(
newBatch
));
config
.
onRepositoryChange
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
newProperties
);
TimeUnit
.
MILLISECONDS
.
sleep
(
50
);
// Does not support this scenario
assertEquals
(
initialTimeout
,
bean
.
getTimeout
());
assertEquals
(
initialBatch
,
bean
.
getBatch
());
}
@Test
public
void
testAutoUpdateWithValueAndProperty
()
throws
Exception
{
int
initialTimeout
=
1000
;
int
initialBatch
=
2000
;
int
newTimeout
=
1001
;
int
newBatch
=
2001
;
Properties
properties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
initialTimeout
),
BATCH_PROPERTY
,
String
.
valueOf
(
initialBatch
));
SimpleConfig
config
=
prepareConfig
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
properties
);
ClassPathXmlApplicationContext
context
=
new
ClassPathXmlApplicationContext
(
"spring/XmlConfigPlaceholderTest9.xml"
);
TestXmlBeanWithInjectedValue
bean
=
context
.
getBean
(
TestXmlBeanWithInjectedValue
.
class
);
assertEquals
(
initialTimeout
,
bean
.
getTimeout
());
assertEquals
(
initialBatch
,
bean
.
getBatch
());
Properties
newProperties
=
assembleProperties
(
TIMEOUT_PROPERTY
,
String
.
valueOf
(
newTimeout
),
BATCH_PROPERTY
,
String
.
valueOf
(
newBatch
));
config
.
onRepositoryChange
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
newProperties
);
TimeUnit
.
MILLISECONDS
.
sleep
(
50
);
assertEquals
(
newTimeout
,
bean
.
getTimeout
());
assertEquals
(
newBatch
,
bean
.
getBatch
());
}
@Test
public
void
testAutoUpdateWithAllKindsOfDataTypes
()
throws
Exception
{
int
someInt
=
1000
;
int
someNewInt
=
1001
;
int
[]
someIntArray
=
{
1
,
2
,
3
,
4
};
int
[]
someNewIntArray
=
{
5
,
6
,
7
,
8
};
long
someLong
=
2000L
;
long
someNewLong
=
2001L
;
short
someShort
=
3000
;
short
someNewShort
=
3001
;
float
someFloat
=
1.2
F
;
float
someNewFloat
=
2.2
F
;
double
someDouble
=
3.10
D
;
double
someNewDouble
=
4.10
D
;
byte
someByte
=
123
;
byte
someNewByte
=
124
;
boolean
someBoolean
=
true
;
boolean
someNewBoolean
=
!
someBoolean
;
String
someString
=
"someString"
;
String
someNewString
=
"someNewString"
;
String
someDateFormat
=
"yyyy-MM-dd HH:mm:ss.SSS"
;
Date
someDate
=
assembleDate
(
2018
,
2
,
23
,
20
,
1
,
2
,
123
);
Date
someNewDate
=
assembleDate
(
2018
,
2
,
23
,
21
,
2
,
3
,
345
);
SimpleDateFormat
simpleDateFormat
=
new
SimpleDateFormat
(
someDateFormat
,
Locale
.
US
);
Properties
properties
=
new
Properties
();
properties
.
setProperty
(
"intProperty"
,
String
.
valueOf
(
someInt
));
properties
.
setProperty
(
"intArrayProperty"
,
Ints
.
join
(
", "
,
someIntArray
));
properties
.
setProperty
(
"longProperty"
,
String
.
valueOf
(
someLong
));
properties
.
setProperty
(
"shortProperty"
,
String
.
valueOf
(
someShort
));
properties
.
setProperty
(
"floatProperty"
,
String
.
valueOf
(
someFloat
));
properties
.
setProperty
(
"doubleProperty"
,
String
.
valueOf
(
someDouble
));
properties
.
setProperty
(
"byteProperty"
,
String
.
valueOf
(
someByte
));
properties
.
setProperty
(
"booleanProperty"
,
String
.
valueOf
(
someBoolean
));
properties
.
setProperty
(
"stringProperty"
,
String
.
valueOf
(
someString
));
properties
.
setProperty
(
"dateFormat"
,
String
.
valueOf
(
someDateFormat
));
properties
.
setProperty
(
"dateProperty"
,
simpleDateFormat
.
format
(
someDate
));
SimpleConfig
config
=
prepareConfig
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
properties
);
ClassPathXmlApplicationContext
context
=
new
ClassPathXmlApplicationContext
(
"spring/XmlConfigPlaceholderTest10.xml"
);
TestAllKindsOfDataTypesBean
bean
=
context
.
getBean
(
TestAllKindsOfDataTypesBean
.
class
);
assertEquals
(
someInt
,
bean
.
getIntProperty
());
assertArrayEquals
(
someIntArray
,
bean
.
getIntArrayProperty
());
assertEquals
(
someLong
,
bean
.
getLongProperty
());
assertEquals
(
someShort
,
bean
.
getShortProperty
());
assertEquals
(
someFloat
,
bean
.
getFloatProperty
(),
0.001
F
);
assertEquals
(
someDouble
,
bean
.
getDoubleProperty
(),
0.001
D
);
assertEquals
(
someByte
,
bean
.
getByteProperty
());
assertEquals
(
someBoolean
,
bean
.
getBooleanProperty
());
assertEquals
(
someString
,
bean
.
getStringProperty
());
assertEquals
(
someDate
,
bean
.
getDateProperty
());
Properties
newProperties
=
new
Properties
();
newProperties
.
setProperty
(
"intProperty"
,
String
.
valueOf
(
someNewInt
));
newProperties
.
setProperty
(
"intArrayProperty"
,
Ints
.
join
(
", "
,
someNewIntArray
));
newProperties
.
setProperty
(
"longProperty"
,
String
.
valueOf
(
someNewLong
));
newProperties
.
setProperty
(
"shortProperty"
,
String
.
valueOf
(
someNewShort
));
newProperties
.
setProperty
(
"floatProperty"
,
String
.
valueOf
(
someNewFloat
));
newProperties
.
setProperty
(
"doubleProperty"
,
String
.
valueOf
(
someNewDouble
));
newProperties
.
setProperty
(
"byteProperty"
,
String
.
valueOf
(
someNewByte
));
newProperties
.
setProperty
(
"booleanProperty"
,
String
.
valueOf
(
someNewBoolean
));
newProperties
.
setProperty
(
"stringProperty"
,
String
.
valueOf
(
someNewString
));
newProperties
.
setProperty
(
"dateFormat"
,
String
.
valueOf
(
someDateFormat
));
newProperties
.
setProperty
(
"dateProperty"
,
simpleDateFormat
.
format
(
someNewDate
));
config
.
onRepositoryChange
(
ConfigConsts
.
NAMESPACE_APPLICATION
,
newProperties
);
TimeUnit
.
MILLISECONDS
.
sleep
(
50
);
assertEquals
(
someNewInt
,
bean
.
getIntProperty
());
assertArrayEquals
(
someNewIntArray
,
bean
.
getIntArrayProperty
());
assertEquals
(
someNewLong
,
bean
.
getLongProperty
());
assertEquals
(
someNewShort
,
bean
.
getShortProperty
());
assertEquals
(
someNewFloat
,
bean
.
getFloatProperty
(),
0.001
F
);
assertEquals
(
someNewDouble
,
bean
.
getDoubleProperty
(),
0.001
D
);
assertEquals
(
someNewByte
,
bean
.
getByteProperty
());
assertEquals
(
someNewBoolean
,
bean
.
getBooleanProperty
());
assertEquals
(
someNewString
,
bean
.
getStringProperty
());
assertEquals
(
someNewDate
,
bean
.
getDateProperty
());
}
public
static
class
TestXmlBeanWithConstructorArgs
{
private
final
int
timeout
;
private
final
int
batch
;
public
TestXmlBeanWithConstructorArgs
(
int
timeout
,
int
batch
)
{
this
.
timeout
=
timeout
;
this
.
batch
=
batch
;
}
public
int
getTimeout
()
{
return
timeout
;
}
public
int
getBatch
()
{
return
batch
;
}
}
public
static
class
TestXmlBeanWithInjectedValue
{
@Value
(
"${timeout}"
)
private
int
timeout
;
private
int
batch
;
public
void
setBatch
(
int
batch
)
{
this
.
batch
=
batch
;
}
public
int
getTimeout
()
{
return
timeout
;
}
public
int
getBatch
()
{
return
batch
;
}
}
static
class
TestAllKindsOfDataTypesBean
{
private
int
intProperty
;
private
int
[]
intArrayProperty
;
private
long
longProperty
;
private
short
shortProperty
;
private
float
floatProperty
;
private
double
doubleProperty
;
private
byte
byteProperty
;
private
boolean
booleanProperty
;
private
String
stringProperty
;
private
Date
dateProperty
;
public
void
setDateProperty
(
Date
dateProperty
)
{
this
.
dateProperty
=
dateProperty
;
}
public
void
setIntProperty
(
int
intProperty
)
{
this
.
intProperty
=
intProperty
;
}
public
void
setIntArrayProperty
(
int
[]
intArrayProperty
)
{
this
.
intArrayProperty
=
intArrayProperty
;
}
public
void
setLongProperty
(
long
longProperty
)
{
this
.
longProperty
=
longProperty
;
}
public
void
setShortProperty
(
short
shortProperty
)
{
this
.
shortProperty
=
shortProperty
;
}
public
void
setFloatProperty
(
float
floatProperty
)
{
this
.
floatProperty
=
floatProperty
;
}
public
void
setDoubleProperty
(
double
doubleProperty
)
{
this
.
doubleProperty
=
doubleProperty
;
}
public
void
setByteProperty
(
byte
byteProperty
)
{
this
.
byteProperty
=
byteProperty
;
}
public
void
setBooleanProperty
(
boolean
booleanProperty
)
{
this
.
booleanProperty
=
booleanProperty
;
}
public
void
setStringProperty
(
String
stringProperty
)
{
this
.
stringProperty
=
stringProperty
;
}
public
int
getIntProperty
()
{
return
intProperty
;
}
public
int
[]
getIntArrayProperty
()
{
return
intArrayProperty
;
}
public
long
getLongProperty
()
{
return
longProperty
;
}
public
short
getShortProperty
()
{
return
shortProperty
;
}
public
float
getFloatProperty
()
{
return
floatProperty
;
}
public
double
getDoubleProperty
()
{
return
doubleProperty
;
}
public
byte
getByteProperty
()
{
return
byteProperty
;
}
public
boolean
getBooleanProperty
()
{
return
booleanProperty
;
}
public
String
getStringProperty
()
{
return
stringProperty
;
}
public
Date
getDateProperty
()
{
return
dateProperty
;
}
}
}
apollo-client/src/test/java/com/ctrip/framework/apollo/spring/config/ConfigPropertySourceTest.java
0 → 100644
View file @
5823daa6
package
com
.
ctrip
.
framework
.
apollo
.
spring
.
config
;
import
static
org
.
junit
.
Assert
.
assertArrayEquals
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
import
static
org
.
mockito
.
Matchers
.
any
;
import
static
org
.
mockito
.
Mockito
.
doAnswer
;
import
static
org
.
mockito
.
Mockito
.
mock
;
import
static
org
.
mockito
.
Mockito
.
times
;
import
static
org
.
mockito
.
Mockito
.
verify
;
import
static
org
.
mockito
.
Mockito
.
when
;
import
com.ctrip.framework.apollo.Config
;
import
com.ctrip.framework.apollo.ConfigChangeListener
;
import
com.google.common.collect.Lists
;
import
com.google.common.collect.Sets
;
import
java.util.List
;
import
java.util.Set
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
import
org.mockito.Mock
;
import
org.mockito.invocation.InvocationOnMock
;
import
org.mockito.runners.MockitoJUnitRunner
;
import
org.mockito.stubbing.Answer
;
@RunWith
(
MockitoJUnitRunner
.
class
)
public
class
ConfigPropertySourceTest
{
private
ConfigPropertySource
configPropertySource
;
@Mock
private
Config
someConfig
;
@Before
public
void
setUp
()
throws
Exception
{
String
someName
=
"someName"
;
configPropertySource
=
new
ConfigPropertySource
(
someName
,
someConfig
);
}
@Test
public
void
testGetPropertyNames
()
throws
Exception
{
String
somePropertyName
=
"somePropertyName"
;
String
anotherPropertyName
=
"anotherPropertyName"
;
Set
<
String
>
somePropertyNames
=
Sets
.
newHashSet
(
somePropertyName
,
anotherPropertyName
);
when
(
someConfig
.
getPropertyNames
()).
thenReturn
(
somePropertyNames
);
String
[]
result
=
configPropertySource
.
getPropertyNames
();
verify
(
someConfig
,
times
(
1
)).
getPropertyNames
();
assertArrayEquals
(
somePropertyNames
.
toArray
(),
result
);
}
@Test
public
void
testGetEmptyPropertyNames
()
throws
Exception
{
when
(
someConfig
.
getPropertyNames
()).
thenReturn
(
Sets
.<
String
>
newHashSet
());
assertEquals
(
0
,
configPropertySource
.
getPropertyNames
().
length
);
}
@Test
public
void
testGetProperty
()
throws
Exception
{
String
somePropertyName
=
"somePropertyName"
;
String
someValue
=
"someValue"
;
when
(
someConfig
.
getProperty
(
somePropertyName
,
null
)).
thenReturn
(
someValue
);
assertEquals
(
someValue
,
configPropertySource
.
getProperty
(
somePropertyName
));
verify
(
someConfig
,
times
(
1
)).
getProperty
(
somePropertyName
,
null
);
}
@Test
public
void
testAddChangeListener
()
throws
Exception
{
ConfigChangeListener
someListener
=
mock
(
ConfigChangeListener
.
class
);
ConfigChangeListener
anotherListener
=
mock
(
ConfigChangeListener
.
class
);
final
List
<
ConfigChangeListener
>
listeners
=
Lists
.
newArrayList
();
doAnswer
(
new
Answer
()
{
@Override
public
Object
answer
(
InvocationOnMock
invocation
)
throws
Throwable
{
listeners
.
add
(
invocation
.
getArgumentAt
(
0
,
ConfigChangeListener
.
class
));
return
Void
.
class
;
}
}).
when
(
someConfig
).
addChangeListener
(
any
(
ConfigChangeListener
.
class
));
configPropertySource
.
addChangeListener
(
someListener
);
configPropertySource
.
addChangeListener
(
anotherListener
);
assertEquals
(
2
,
listeners
.
size
());
assertTrue
(
listeners
.
containsAll
(
Lists
.
newArrayList
(
someListener
,
anotherListener
)));
}
}
apollo-client/src/test/java/com/ctrip/framework/apollo/spring/property/PlaceholderHelperTest.java
0 → 100644
View file @
5823daa6
package
com
.
ctrip
.
framework
.
apollo
.
spring
.
property
;
import
static
org
.
junit
.
Assert
.
assertEquals
;
import
static
org
.
junit
.
Assert
.
assertTrue
;
import
com.google.common.collect.Sets
;
import
org.junit.Before
;
import
org.junit.Test
;
public
class
PlaceholderHelperTest
{
private
PlaceholderHelper
placeholderHelper
;
@Before
public
void
setUp
()
throws
Exception
{
placeholderHelper
=
new
PlaceholderHelper
();
}
@Test
public
void
testExtractPlaceholderKeys
()
throws
Exception
{
check
(
"${some.key}"
,
"some.key"
);
check
(
"${some.key:100}"
,
"some.key"
);
check
(
"${some.key:${some.other.key}}"
,
"some.key"
,
"some.other.key"
);
check
(
"${some.key:${some.other.key:100}}"
,
"some.key"
,
"some.other.key"
);
}
@Test
public
void
testExtractNestedPlaceholderKeys
()
throws
Exception
{
check
(
"${${some.key}}"
,
"some.key"
);
check
(
"${${some.key:other.key}}"
,
"some.key"
);
check
(
"${${some.key}:100}"
,
"some.key"
);
check
(
"${${some.key}:${another.key}}"
,
"some.key"
,
"another.key"
);
}
@Test
public
void
testExtractComplexNestedPlaceholderKeys
()
throws
Exception
{
check
(
"${${a}1${b}:3.${c:${d:100}}}"
,
"a"
,
"b"
,
"c"
,
"d"
);
check
(
"${1${a}2${b}3:4.${c:5${d:100}6}7}"
,
"a"
,
"b"
,
"c"
,
"d"
);
}
@Test
public
void
testExtractPlaceholderKeysFromExpression
()
throws
Exception
{
check
(
"#{new java.text.SimpleDateFormat('${some.key}').parse('${another.key}')}"
,
"some.key"
,
"another.key"
);
check
(
"#{new java.text.SimpleDateFormat('${some.key:abc}').parse('${another.key:100}')}"
,
"some.key"
,
"another.key"
);
check
(
"#{new java.text.SimpleDateFormat('${some.key:${some.other.key}}').parse('${another.key}')}"
,
"some.key"
,
"another.key"
,
"some.other.key"
);
check
(
"#{new java.text.SimpleDateFormat('${some.key:${some.other.key:abc}}').parse('${another.key}')}"
,
"some.key"
,
"another.key"
,
"some.other.key"
);
check
(
"#{new java.text.SimpleDateFormat('${${some.key}}').parse('${${another.key:other.key}}')}"
,
"some.key"
,
"another.key"
);
assertTrue
(
placeholderHelper
.
extractPlaceholderKeys
(
"#{systemProperties[some.key] ?: 123}"
).
isEmpty
());
assertTrue
(
placeholderHelper
.
extractPlaceholderKeys
(
"#{ T(java.lang.Math).random() * 100.0 }"
).
isEmpty
());
}
@Test
public
void
testExtractInvalidPlaceholderKeys
()
throws
Exception
{
assertTrue
(
placeholderHelper
.
extractPlaceholderKeys
(
"some.key"
).
isEmpty
());
assertTrue
(
placeholderHelper
.
extractPlaceholderKeys
(
"some.key:100"
).
isEmpty
());
}
private
void
check
(
String
propertyString
,
String
...
expectedPlaceholders
)
{
assertEquals
(
Sets
.
newHashSet
(
expectedPlaceholders
),
placeholderHelper
.
extractPlaceholderKeys
(
propertyString
));
}
}
apollo-client/src/test/java/com/ctrip/framework/apollo/util/ConfigUtilTest.java
View file @
5823daa6
...
@@ -3,7 +3,6 @@ package com.ctrip.framework.apollo.util;
...
@@ -3,7 +3,6 @@ package com.ctrip.framework.apollo.util;
import
com.ctrip.framework.apollo.core.ConfigConsts
;
import
com.ctrip.framework.apollo.core.ConfigConsts
;
import
org.junit.After
;
import
org.junit.After
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.junit.Test
;
import
static
org
.
junit
.
Assert
.*;
import
static
org
.
junit
.
Assert
.*;
...
@@ -22,6 +21,7 @@ public class ConfigUtilTest {
...
@@ -22,6 +21,7 @@ public class ConfigUtilTest {
System
.
clearProperty
(
"apollo.longPollQPS"
);
System
.
clearProperty
(
"apollo.longPollQPS"
);
System
.
clearProperty
(
"apollo.configCacheSize"
);
System
.
clearProperty
(
"apollo.configCacheSize"
);
System
.
clearProperty
(
"apollo.longPollingInitialDelayInMills"
);
System
.
clearProperty
(
"apollo.longPollingInitialDelayInMills"
);
System
.
clearProperty
(
"apollo.autoUpdateInjectedSpringProperties"
);
}
}
@Test
@Test
...
@@ -173,4 +173,16 @@ public class ConfigUtilTest {
...
@@ -173,4 +173,16 @@ public class ConfigUtilTest {
assertTrue
(
configUtil
.
getLongPollingInitialDelayInMills
()
>
0
);
assertTrue
(
configUtil
.
getLongPollingInitialDelayInMills
()
>
0
);
}
}
}
\ No newline at end of file
@Test
public
void
testCustomizeAutoUpdateInjectedSpringProperties
()
throws
Exception
{
boolean
someAutoUpdateInjectedSpringProperties
=
false
;
System
.
setProperty
(
"apollo.autoUpdateInjectedSpringProperties"
,
String
.
valueOf
(
someAutoUpdateInjectedSpringProperties
));
ConfigUtil
configUtil
=
new
ConfigUtil
();
assertEquals
(
someAutoUpdateInjectedSpringProperties
,
configUtil
.
isAutoUpdateInjectedSpringPropertiesEnabled
());
}
}
apollo-client/src/test/resources/spring/XmlConfigPlaceholderTest10.xml
0 → 100644
View file @
5823daa6
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns=
"http://www.springframework.org/schema/beans"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xmlns:apollo=
"http://www.ctrip.com/schema/apollo"
xsi:schemaLocation=
"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.ctrip.com/schema/apollo http://www.ctrip.com/schema/apollo.xsd"
>
<apollo:config
/>
<bean
class=
"com.ctrip.framework.apollo.spring.XmlConfigPlaceholderAutoUpdateTest.TestAllKindsOfDataTypesBean"
>
<property
name=
"intProperty"
value=
"${intProperty}"
/>
<property
name=
"intArrayProperty"
value=
"${intArrayProperty}"
/>
<property
name=
"longProperty"
value=
"${longProperty}"
/>
<property
name=
"shortProperty"
value=
"${shortProperty}"
/>
<property
name=
"floatProperty"
value=
"${floatProperty}"
/>
<property
name=
"doubleProperty"
value=
"${doubleProperty}"
/>
<property
name=
"byteProperty"
value=
"${byteProperty}"
/>
<property
name=
"booleanProperty"
value=
"${booleanProperty}"
/>
<property
name=
"stringProperty"
value=
"${stringProperty}"
/>
<property
name=
"dateProperty"
value=
"#{new java.text.SimpleDateFormat('${dateFormat}').parse('${dateProperty}')}"
/>
</bean>
</beans>
apollo-client/src/test/resources/spring/XmlConfigPlaceholderTest7.xml
0 → 100644
View file @
5823daa6
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns=
"http://www.springframework.org/schema/beans"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xmlns:apollo=
"http://www.ctrip.com/schema/apollo"
xsi:schemaLocation=
"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.ctrip.com/schema/apollo http://www.ctrip.com/schema/apollo.xsd"
>
<apollo:config
/>
<bean
class=
"com.ctrip.framework.apollo.spring.XmlConfigPlaceholderTest.TestXmlBean"
>
<property
name=
"timeout"
value=
"${timeout}"
/>
<property
name=
"batch"
value=
"${batch}"
/>
</bean>
</beans>
apollo-client/src/test/resources/spring/XmlConfigPlaceholderTest8.xml
0 → 100644
View file @
5823daa6
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns=
"http://www.springframework.org/schema/beans"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xmlns:apollo=
"http://www.ctrip.com/schema/apollo"
xsi:schemaLocation=
"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.ctrip.com/schema/apollo http://www.ctrip.com/schema/apollo.xsd"
>
<apollo:config
/>
<bean
class=
"com.ctrip.framework.apollo.spring.XmlConfigPlaceholderAutoUpdateTest.TestXmlBeanWithConstructorArgs"
>
<constructor-arg
index=
"0"
value=
"${timeout}"
/>
<constructor-arg
index=
"1"
value=
"${batch}"
/>
</bean>
</beans>
apollo-client/src/test/resources/spring/XmlConfigPlaceholderTest9.xml
0 → 100644
View file @
5823daa6
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns=
"http://www.springframework.org/schema/beans"
xmlns:xsi=
"http://www.w3.org/2001/XMLSchema-instance"
xmlns:context=
"http://www.springframework.org/schema/context"
xmlns:apollo=
"http://www.ctrip.com/schema/apollo"
xsi:schemaLocation=
"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.ctrip.com/schema/apollo http://www.ctrip.com/schema/apollo.xsd"
>
<context:annotation-config
/>
<apollo:config/>
<bean
class=
"com.ctrip.framework.apollo.spring.XmlConfigPlaceholderAutoUpdateTest.TestXmlBeanWithInjectedValue"
>
<property
name=
"batch"
value=
"${batch}"
/>
</bean>
</beans>
apollo-core/src/test/resources/META-INF/some-invalid-app.properties
View file @
5823daa6
appid
=
110402
appid
=
110402
\ No newline at end of file
apollo-demo/src/main/java/com/ctrip/framework/apollo/demo/api/ApolloConfigDemo.java
View file @
5823daa6
...
@@ -46,7 +46,7 @@ public class ApolloConfigDemo {
...
@@ -46,7 +46,7 @@ public class ApolloConfigDemo {
};
};
config
=
ConfigService
.
getAppConfig
();
config
=
ConfigService
.
getAppConfig
();
config
.
addChangeListener
(
changeListener
);
config
.
addChangeListener
(
changeListener
);
publicConfig
=
ConfigService
.
getConfig
(
"
FX
.apollo"
);
publicConfig
=
ConfigService
.
getConfig
(
"
TEST1
.apollo"
);
publicConfig
.
addChangeListener
(
changeListener
);
publicConfig
.
addChangeListener
(
changeListener
);
applicationConfigFile
=
ConfigService
.
getConfigFile
(
"application"
,
ConfigFileFormat
.
Properties
);
applicationConfigFile
=
ConfigService
.
getConfigFile
(
"application"
,
ConfigFileFormat
.
Properties
);
xmlConfigFile
=
ConfigService
.
getConfigFile
(
"datasources"
,
ConfigFileFormat
.
XML
);
xmlConfigFile
=
ConfigService
.
getConfigFile
(
"datasources"
,
ConfigFileFormat
.
XML
);
...
...
apollo-demo/src/main/java/com/ctrip/framework/apollo/demo/spring/common/bean/AnnotatedBean.java
View file @
5823daa6
...
@@ -3,34 +3,29 @@ package com.ctrip.framework.apollo.demo.spring.common.bean;
...
@@ -3,34 +3,29 @@ package com.ctrip.framework.apollo.demo.spring.common.bean;
import
org.slf4j.Logger
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.cloud.context.config.annotation.RefreshScope
;
import
org.springframework.stereotype.Component
;
import
org.springframework.stereotype.Component
;
import
javax.annotation.PostConstruct
;
/**
/**
* @author Jason Song(song_s@ctrip.com)
* @author Jason Song(song_s@ctrip.com)
*/
*/
@RefreshScope
@Component
(
"annotatedBean"
)
@Component
(
"annotatedBean"
)
public
class
AnnotatedBean
{
public
class
AnnotatedBean
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
AnnotatedBean
.
class
);
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
AnnotatedBean
.
class
);
@Value
(
"${timeout:200}"
)
private
int
timeout
;
private
int
timeout
;
private
int
batch
;
private
int
batch
;
@PostConstruct
void
initialize
()
{
logger
.
info
(
"timeout is initialized as {}"
,
timeout
);
logger
.
info
(
"batch is initialized as {}"
,
batch
);
}
@Value
(
"${batch:100}"
)
@Value
(
"${batch:100}"
)
public
void
setBatch
(
int
batch
)
{
public
void
setBatch
(
int
batch
)
{
logger
.
info
(
"updating batch, old value: {}, new value: {}"
,
this
.
batch
,
batch
);
this
.
batch
=
batch
;
this
.
batch
=
batch
;
}
}
@Value
(
"${timeout:200}"
)
public
void
setTimeout
(
int
timeout
)
{
logger
.
info
(
"updating timeout, old value: {}, new value: {}"
,
this
.
timeout
,
timeout
);
this
.
timeout
=
timeout
;
}
@Override
@Override
public
String
toString
()
{
public
String
toString
()
{
...
...
apollo-demo/src/main/java/com/ctrip/framework/apollo/demo/spring/common/config/AnotherAppConfig.java
View file @
5823daa6
...
@@ -8,6 +8,6 @@ import org.springframework.context.annotation.Configuration;
...
@@ -8,6 +8,6 @@ import org.springframework.context.annotation.Configuration;
* @author Jason Song(song_s@ctrip.com)
* @author Jason Song(song_s@ctrip.com)
*/
*/
@Configuration
@Configuration
@EnableApolloConfig
(
value
=
"
FX
.apollo"
,
order
=
11
)
@EnableApolloConfig
(
value
=
"
TEST1
.apollo"
,
order
=
11
)
public
class
AnotherAppConfig
{
public
class
AnotherAppConfig
{
}
}
apollo-demo/src/main/java/com/ctrip/framework/apollo/demo/spring/common/refresh/ApolloRefreshConfig.java
deleted
100644 → 0
View file @
7edfb1aa
package
com
.
ctrip
.
framework
.
apollo
.
demo
.
spring
.
common
.
refresh
;
import
com.ctrip.framework.apollo.demo.spring.common.bean.AnnotatedBean
;
import
com.ctrip.framework.apollo.model.ConfigChangeEvent
;
import
com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.cloud.context.scope.refresh.RefreshScope
;
import
org.springframework.stereotype.Component
;
/**
* To refresh the config bean when config is changed
*
* @author Jason Song(song_s@ctrip.com)
*/
@Component
public
class
ApolloRefreshConfig
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
ApolloRefreshConfig
.
class
);
@Autowired
private
RefreshScope
refreshScope
;
@Autowired
private
AnnotatedBean
annotatedBean
;
@ApolloConfigChangeListener
({
"application"
,
"FX.apollo"
})
private
void
onChange
(
ConfigChangeEvent
changeEvent
)
{
if
(
changeEvent
.
isChanged
(
"timeout"
)
||
changeEvent
.
isChanged
(
"batch"
))
{
logger
.
info
(
"before refresh {}"
,
annotatedBean
.
toString
());
//could also call refreshScope.refreshAll();
refreshScope
.
refresh
(
"annotatedBean"
);
logger
.
info
(
"after refresh {}"
,
annotatedBean
.
toString
());
}
}
}
apollo-demo/src/main/java/com/ctrip/framework/apollo/demo/spring/javaConfigDemo/AnnotationApplication.java
View file @
5823daa6
package
com
.
ctrip
.
framework
.
apollo
.
demo
.
spring
.
javaConfigDemo
;
package
com
.
ctrip
.
framework
.
apollo
.
demo
.
spring
.
javaConfigDemo
;
import
com.ctrip.framework.apollo.demo.spring.common.bean.AnnotatedBean
;
import
com.google.common.base.Charsets
;
import
com.google.common.base.Strings
;
import
java.io.BufferedReader
;
import
java.io.IOException
;
import
java.io.InputStreamReader
;
import
org.springframework.context.ApplicationContext
;
import
org.springframework.context.annotation.AnnotationConfigApplicationContext
;
import
org.springframework.context.annotation.AnnotationConfigApplicationContext
;
import
java.util.Scanner
;
import
java.util.Scanner
;
...
@@ -8,14 +15,19 @@ import java.util.Scanner;
...
@@ -8,14 +15,19 @@ import java.util.Scanner;
* @author Jason Song(song_s@ctrip.com)
* @author Jason Song(song_s@ctrip.com)
*/
*/
public
class
AnnotationApplication
{
public
class
AnnotationApplication
{
public
static
void
main
(
String
[]
args
)
{
public
static
void
main
(
String
[]
args
)
throws
IOException
{
new
AnnotationConfigApplicationContext
(
"com.ctrip.framework.apollo.demo.spring.common"
,
ApplicationContext
context
=
new
AnnotationConfigApplicationContext
(
"com.ctrip.framework.apollo.demo.spring.common"
);
"com.ctrip.framework.apollo.demo.spring.javaConfigDemo"
);
AnnotatedBean
annotatedBean
=
context
.
getBean
(
AnnotatedBean
.
class
);
onKeyExit
();
}
System
.
out
.
println
(
"AnnotationApplication Demo. Input any key except quit to print the values. Input quit to exit."
);
while
(
true
)
{
System
.
out
.
print
(
"> "
);
String
input
=
new
BufferedReader
(
new
InputStreamReader
(
System
.
in
,
Charsets
.
UTF_8
)).
readLine
();
if
(!
Strings
.
isNullOrEmpty
(
input
)
&&
input
.
trim
().
equalsIgnoreCase
(
"quit"
))
{
System
.
exit
(
0
);
}
private
static
void
onKeyExit
()
{
System
.
out
.
println
(
annotatedBean
.
toString
());
System
.
out
.
println
(
"Press Enter to exit..."
);
}
new
Scanner
(
System
.
in
).
nextLine
();
}
}
}
}
apollo-demo/src/main/java/com/ctrip/framework/apollo/demo/spring/javaConfigDemo/config/RefreshScopeConfig.java
deleted
100644 → 0
View file @
7edfb1aa
package
com
.
ctrip
.
framework
.
apollo
.
demo
.
spring
.
javaConfigDemo
.
config
;
import
org.springframework.cloud.autoconfigure.RefreshAutoConfiguration
;
import
org.springframework.context.annotation.Configuration
;
import
org.springframework.context.annotation.Import
;
/**
* to support RefreshScope
* @author Jason Song(song_s@ctrip.com)
*/
@Configuration
@Import
(
RefreshAutoConfiguration
.
class
)
public
class
RefreshScopeConfig
{
}
apollo-demo/src/main/java/com/ctrip/framework/apollo/demo/spring/springBootDemo/SpringBootSampleApplication.java
View file @
5823daa6
package
com
.
ctrip
.
framework
.
apollo
.
demo
.
spring
.
springBootDemo
;
package
com
.
ctrip
.
framework
.
apollo
.
demo
.
spring
.
springBootDemo
;
import
com.ctrip.framework.apollo.demo.spring.springBootDemo.config.SampleRedisConfig
;
import
java.io.BufferedReader
;
import
java.io.IOException
;
import
java.io.InputStreamReader
;
import
org.springframework.boot.autoconfigure.SpringBootApplication
;
import
org.springframework.boot.autoconfigure.SpringBootApplication
;
import
org.springframework.boot.builder.SpringApplicationBuilder
;
import
org.springframework.boot.builder.SpringApplicationBuilder
;
import
org.springframework.context.ApplicationContext
;
import
java.util.Scanner
;
import
com.ctrip.framework.apollo.demo.spring.common.bean.AnnotatedBean
;
import
com.google.common.base.Charsets
;
import
com.google.common.base.Strings
;
/**
/**
* @author Jason Song(song_s@ctrip.com)
* @author Jason Song(song_s@ctrip.com)
...
@@ -13,13 +21,21 @@ import java.util.Scanner;
...
@@ -13,13 +21,21 @@ import java.util.Scanner;
})
})
public
class
SpringBootSampleApplication
{
public
class
SpringBootSampleApplication
{
public
static
void
main
(
String
[]
args
)
{
public
static
void
main
(
String
[]
args
)
throws
IOException
{
new
SpringApplicationBuilder
(
SpringBootSampleApplication
.
class
).
run
(
args
);
ApplicationContext
context
=
new
SpringApplicationBuilder
(
SpringBootSampleApplication
.
class
).
run
(
args
);
onKeyExit
();
AnnotatedBean
annotatedBean
=
context
.
getBean
(
AnnotatedBean
.
class
);
}
SampleRedisConfig
redisConfig
=
context
.
getBean
(
SampleRedisConfig
.
class
);
System
.
out
.
println
(
"SpringBootSampleApplication Demo. Input any key except quit to print the values. Input quit to exit."
);
while
(
true
)
{
System
.
out
.
print
(
"> "
);
String
input
=
new
BufferedReader
(
new
InputStreamReader
(
System
.
in
,
Charsets
.
UTF_8
)).
readLine
();
if
(!
Strings
.
isNullOrEmpty
(
input
)
&&
input
.
trim
().
equalsIgnoreCase
(
"quit"
))
{
System
.
exit
(
0
);
}
private
static
void
onKeyExit
()
{
System
.
out
.
println
(
annotatedBean
.
toString
());
System
.
out
.
println
(
"Press Enter to exit..."
);
System
.
out
.
println
(
redisConfig
.
toString
()
);
new
Scanner
(
System
.
in
).
nextLine
();
}
}
}
}
}
apollo-demo/src/main/java/com/ctrip/framework/apollo/demo/spring/springBootDemo/refresh/SpringBootApolloRefreshConfig.java
View file @
5823daa6
package
com
.
ctrip
.
framework
.
apollo
.
demo
.
spring
.
springBootDemo
.
refresh
;
package
com
.
ctrip
.
framework
.
apollo
.
demo
.
spring
.
springBootDemo
.
refresh
;
import
com.ctrip.framework.apollo.demo.spring.common.refresh.ApolloRefreshConfig
;
import
com.ctrip.framework.apollo.demo.spring.springBootDemo.config.SampleRedisConfig
;
import
com.ctrip.framework.apollo.model.ConfigChangeEvent
;
import
com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener
;
import
org.slf4j.Logger
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.beans.factory.annotation.Autowired
;
...
@@ -12,6 +7,10 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
...
@@ -12,6 +7,10 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import
org.springframework.cloud.context.scope.refresh.RefreshScope
;
import
org.springframework.cloud.context.scope.refresh.RefreshScope
;
import
org.springframework.stereotype.Component
;
import
org.springframework.stereotype.Component
;
import
com.ctrip.framework.apollo.demo.spring.springBootDemo.config.SampleRedisConfig
;
import
com.ctrip.framework.apollo.model.ConfigChangeEvent
;
import
com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener
;
/**
/**
* @author Jason Song(song_s@ctrip.com)
* @author Jason Song(song_s@ctrip.com)
*/
*/
...
@@ -20,9 +19,6 @@ import org.springframework.stereotype.Component;
...
@@ -20,9 +19,6 @@ import org.springframework.stereotype.Component;
public
class
SpringBootApolloRefreshConfig
{
public
class
SpringBootApolloRefreshConfig
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
SpringBootApolloRefreshConfig
.
class
);
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
SpringBootApolloRefreshConfig
.
class
);
@Autowired
private
ApolloRefreshConfig
apolloRefreshConfig
;
@Autowired
@Autowired
private
SampleRedisConfig
sampleRedisConfig
;
private
SampleRedisConfig
sampleRedisConfig
;
...
@@ -31,6 +27,17 @@ public class SpringBootApolloRefreshConfig {
...
@@ -31,6 +27,17 @@ public class SpringBootApolloRefreshConfig {
@ApolloConfigChangeListener
@ApolloConfigChangeListener
public
void
onChange
(
ConfigChangeEvent
changeEvent
)
{
public
void
onChange
(
ConfigChangeEvent
changeEvent
)
{
boolean
redisCacheKeysChanged
=
false
;
for
(
String
changedKey
:
changeEvent
.
changedKeys
())
{
if
(
changedKey
.
startsWith
(
"redis.cache"
))
{
redisCacheKeysChanged
=
true
;
break
;
}
}
if
(!
redisCacheKeysChanged
)
{
return
;
}
logger
.
info
(
"before refresh {}"
,
sampleRedisConfig
.
toString
());
logger
.
info
(
"before refresh {}"
,
sampleRedisConfig
.
toString
());
refreshScope
.
refresh
(
"sampleRedisConfig"
);
refreshScope
.
refresh
(
"sampleRedisConfig"
);
logger
.
info
(
"after refresh {}"
,
sampleRedisConfig
.
toString
());
logger
.
info
(
"after refresh {}"
,
sampleRedisConfig
.
toString
());
...
...
apollo-demo/src/main/java/com/ctrip/framework/apollo/demo/spring/xmlConfigDemo/XmlApplication.java
View file @
5823daa6
package
com
.
ctrip
.
framework
.
apollo
.
demo
.
spring
.
xmlConfigDemo
;
package
com
.
ctrip
.
framework
.
apollo
.
demo
.
spring
.
xmlConfigDemo
;
import
com.google.common.base.Strings
;
import
java.io.BufferedReader
;
import
java.io.IOException
;
import
java.io.InputStreamReader
;
import
org.springframework.context.ApplicationContext
;
import
org.springframework.context.support.ClassPathXmlApplicationContext
;
import
org.springframework.context.support.ClassPathXmlApplicationContext
;
import
java.util.Scanner
;
import
com.ctrip.framework.apollo.demo.spring.xmlConfigDemo.bean.XmlBean
;
import
com.google.common.base.Charsets
;
/**
/**
* @author Jason Song(song_s@ctrip.com)
* @author Jason Song(song_s@ctrip.com)
*/
*/
public
class
XmlApplication
{
public
class
XmlApplication
{
public
static
void
main
(
String
[]
args
)
{
public
static
void
main
(
String
[]
args
)
throws
IOException
{
new
ClassPathXmlApplicationContext
(
"spring.xml"
);
ApplicationContext
context
=
new
ClassPathXmlApplicationContext
(
"spring.xml"
);
onKeyExit
();
XmlBean
xmlBean
=
context
.
getBean
(
XmlBean
.
class
);
}
System
.
out
.
println
(
"XmlApplication Demo. Input any key except quit to print the values. Input quit to exit."
);
while
(
true
)
{
System
.
out
.
print
(
"> "
);
String
input
=
new
BufferedReader
(
new
InputStreamReader
(
System
.
in
,
Charsets
.
UTF_8
)).
readLine
();
if
(!
Strings
.
isNullOrEmpty
(
input
)
&&
input
.
trim
().
equalsIgnoreCase
(
"quit"
))
{
System
.
exit
(
0
);
}
private
static
void
onKeyExit
()
{
System
.
out
.
println
(
xmlBean
.
toString
());
System
.
out
.
println
(
"Press Enter to exit..."
);
}
new
Scanner
(
System
.
in
).
nextLine
();
}
}
}
}
apollo-demo/src/main/java/com/ctrip/framework/apollo/demo/spring/xmlConfigDemo/bean/XmlBean.java
View file @
5823daa6
...
@@ -29,4 +29,9 @@ public class XmlBean {
...
@@ -29,4 +29,9 @@ public class XmlBean {
public
int
getBatch
()
{
public
int
getBatch
()
{
return
batch
;
return
batch
;
}
}
@Override
public
String
toString
()
{
return
String
.
format
(
"[XmlBean] timeout: %d, batch: %d"
,
timeout
,
batch
);
}
}
}
apollo-demo/src/main/java/com/ctrip/framework/apollo/demo/spring/xmlConfigDemo/refresh/ManualRefreshUtil.java
deleted
100644 → 0
View file @
7edfb1aa
package
com
.
ctrip
.
framework
.
apollo
.
demo
.
spring
.
xmlConfigDemo
.
refresh
;
import
com.ctrip.framework.apollo.Config
;
import
com.ctrip.framework.apollo.demo.spring.xmlConfigDemo.bean.XmlBean
;
import
com.ctrip.framework.apollo.model.ConfigChangeEvent
;
import
com.ctrip.framework.apollo.spring.annotation.ApolloConfig
;
import
com.ctrip.framework.apollo.spring.annotation.ApolloConfigChangeListener
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
org.springframework.beans.factory.annotation.Autowired
;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public
class
ManualRefreshUtil
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
ManualRefreshUtil
.
class
);
@ApolloConfig
private
Config
config
;
@Autowired
private
XmlBean
xmlBean
;
@ApolloConfigChangeListener
private
void
onChange
(
ConfigChangeEvent
changeEvent
)
{
if
(
changeEvent
.
isChanged
(
"timeout"
))
{
logger
.
info
(
"Manually refreshing xmlBean.timeout"
);
xmlBean
.
setTimeout
(
config
.
getIntProperty
(
"timeout"
,
xmlBean
.
getTimeout
()));
}
if
(
changeEvent
.
isChanged
(
"batch"
))
{
logger
.
info
(
"Manually refreshing xmlBean.batch"
);
xmlBean
.
setBatch
(
config
.
getIntProperty
(
"batch"
,
xmlBean
.
getBatch
()));
}
}
}
apollo-demo/src/main/resources/application.yml
View file @
5823daa6
apollo
:
apollo
:
bootstrap
:
bootstrap
:
enabled
:
true
enabled
:
true
# will inject 'application' and '
FX
.apollo' namespaces in bootstrap phase
# will inject 'application' and '
TEST1
.apollo' namespaces in bootstrap phase
namespaces
:
application,
FX
.apollo
namespaces
:
application,
TEST1
.apollo
apollo-demo/src/main/resources/spring.xml
View file @
5823daa6
...
@@ -7,18 +7,12 @@
...
@@ -7,18 +7,12 @@
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
http://www.ctrip.com/schema/apollo http://www.ctrip.com/schema/apollo.xsd"
>
http://www.ctrip.com/schema/apollo http://www.ctrip.com/schema/apollo.xsd"
>
<apollo:config
order=
"10"
/>
<apollo:config
order=
"10"
/>
<apollo:config
namespaces=
"
FX
.apollo"
order=
"11"
/>
<apollo:config
namespaces=
"
TEST1
.apollo"
order=
"11"
/>
<bean
class=
"com.ctrip.framework.apollo.demo.spring.xmlConfigDemo.bean.XmlBean"
>
<bean
class=
"com.ctrip.framework.apollo.demo.spring.xmlConfigDemo.bean.XmlBean"
>
<property
name=
"timeout"
value=
"${timeout:200}"
/>
<property
name=
"timeout"
value=
"${timeout:200}"
/>
<property
name=
"batch"
value=
"${batch:100}"
/>
<property
name=
"batch"
value=
"${batch:100}"
/>
</bean>
</bean>
<bean
class=
"com.ctrip.framework.apollo.demo.spring.xmlConfigDemo.refresh.ManualRefreshUtil"
/>
<context:annotation-config
/>
<!-- to support RefreshScope -->
<bean
class=
"org.springframework.cloud.autoconfigure.RefreshAutoConfiguration"
/>
<context:component-scan
base-package=
"com.ctrip.framework.apollo.demo.spring.common.bean,com.ctrip.framework.apollo.demo.spring.common.refresh"
/>
</beans>
</beans>
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment