Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
A
apollo
Project
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
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
openSource
apollo
Commits
b9fca2d9
Commit
b9fca2d9
authored
Apr 30, 2017
by
张乐
Committed by
GitHub
Apr 30, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #606 from nobodyiam/configfile-change-listener
add config file change listener
parents
bd1832bf
942fffdf
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
287 additions
and
6 deletions
+287
-6
ConfigFile.java
.../src/main/java/com/ctrip/framework/apollo/ConfigFile.java
+7
-0
ConfigFileChangeListener.java
.../com/ctrip/framework/apollo/ConfigFileChangeListener.java
+14
-0
AbstractConfigFile.java
.../ctrip/framework/apollo/internals/AbstractConfigFile.java
+62
-1
PlainTextConfigFile.java
...ctrip/framework/apollo/internals/PlainTextConfigFile.java
+7
-0
PropertiesConfigFile.java
...trip/framework/apollo/internals/PropertiesConfigFile.java
+6
-5
ConfigFileChangeEvent.java
...m/ctrip/framework/apollo/model/ConfigFileChangeEvent.java
+56
-0
ConfigServiceTest.java
...st/java/com/ctrip/framework/apollo/ConfigServiceTest.java
+5
-0
DefaultConfigManagerTest.java
.../framework/apollo/internals/DefaultConfigManagerTest.java
+6
-0
PropertiesConfigFileTest.java
.../framework/apollo/internals/PropertiesConfigFileTest.java
+23
-0
XmlConfigFileTest.java
...m/ctrip/framework/apollo/internals/XmlConfigFileTest.java
+93
-0
ApolloConfigDemo.java
...com/ctrip/framework/apollo/demo/api/ApolloConfigDemo.java
+8
-0
No files found.
apollo-client/src/main/java/com/ctrip/framework/apollo/ConfigFile.java
View file @
b9fca2d9
...
...
@@ -29,4 +29,11 @@ public interface ConfigFile {
* @return the config file format enum
*/
ConfigFileFormat
getConfigFileFormat
();
/**
* Add change listener to this config file instance.
*
* @param listener the config file change listener
*/
void
addChangeListener
(
ConfigFileChangeListener
listener
);
}
apollo-client/src/main/java/com/ctrip/framework/apollo/ConfigFileChangeListener.java
0 → 100644
View file @
b9fca2d9
package
com
.
ctrip
.
framework
.
apollo
;
import
com.ctrip.framework.apollo.model.ConfigFileChangeEvent
;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public
interface
ConfigFileChangeListener
{
/**
* Invoked when there is any config change for the namespace.
* @param changeEvent the event for this change
*/
void
onChange
(
ConfigFileChangeEvent
changeEvent
);
}
apollo-client/src/main/java/com/ctrip/framework/apollo/internals/AbstractConfigFile.java
View file @
b9fca2d9
package
com
.
ctrip
.
framework
.
apollo
.
internals
;
import
java.util.List
;
import
java.util.Objects
;
import
java.util.Properties
;
import
java.util.concurrent.ExecutorService
;
import
java.util.concurrent.Executors
;
import
java.util.concurrent.atomic.AtomicReference
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
com.ctrip.framework.apollo.ConfigFile
;
import
com.ctrip.framework.apollo.ConfigFileChangeListener
;
import
com.ctrip.framework.apollo.core.utils.ApolloThreadFactory
;
import
com.ctrip.framework.apollo.enums.PropertyChangeType
;
import
com.ctrip.framework.apollo.model.ConfigFileChangeEvent
;
import
com.ctrip.framework.apollo.tracer.Tracer
;
import
com.ctrip.framework.apollo.tracer.spi.Transaction
;
import
com.ctrip.framework.apollo.util.ExceptionUtil
;
import
com.google.common.collect.Lists
;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public
abstract
class
AbstractConfigFile
implements
ConfigFile
,
RepositoryChangeListener
{
private
static
final
Logger
logger
=
LoggerFactory
.
getLogger
(
AbstractConfigFile
.
class
);
private
static
ExecutorService
m_executorService
;
protected
ConfigRepository
m_configRepository
;
protected
String
m_namespace
;
protected
AtomicReference
<
Properties
>
m_configProperties
;
private
List
<
ConfigFileChangeListener
>
m_listeners
=
Lists
.
newCopyOnWriteArrayList
();
static
{
m_executorService
=
Executors
.
newCachedThreadPool
(
ApolloThreadFactory
.
create
(
"ConfigFile"
,
true
));
}
public
AbstractConfigFile
(
String
namespace
,
ConfigRepository
configRepository
)
{
m_configRepository
=
configRepository
;
...
...
@@ -45,6 +62,8 @@ public abstract class AbstractConfigFile implements ConfigFile, RepositoryChange
return
m_namespace
;
}
protected
abstract
void
update
(
Properties
newProperties
);
@Override
public
synchronized
void
onRepositoryChange
(
String
namespace
,
Properties
newProperties
)
{
if
(
newProperties
.
equals
(
m_configProperties
.
get
()))
{
...
...
@@ -53,9 +72,51 @@ public abstract class AbstractConfigFile implements ConfigFile, RepositoryChange
Properties
newConfigProperties
=
new
Properties
();
newConfigProperties
.
putAll
(
newProperties
);
m_configProperties
.
set
(
newConfigProperties
);
String
oldValue
=
getContent
();
update
(
newProperties
);
String
newValue
=
getContent
();
PropertyChangeType
changeType
=
PropertyChangeType
.
MODIFIED
;
if
(
oldValue
==
null
)
{
changeType
=
PropertyChangeType
.
ADDED
;
}
else
if
(
newValue
==
null
)
{
changeType
=
PropertyChangeType
.
DELETED
;
}
this
.
fireConfigChange
(
new
ConfigFileChangeEvent
(
m_namespace
,
oldValue
,
newValue
,
changeType
));
Tracer
.
logEvent
(
"Apollo.Client.ConfigChanges"
,
m_namespace
);
}
@Override
public
void
addChangeListener
(
ConfigFileChangeListener
listener
)
{
if
(!
m_listeners
.
contains
(
listener
))
{
m_listeners
.
add
(
listener
);
}
}
private
void
fireConfigChange
(
final
ConfigFileChangeEvent
changeEvent
)
{
for
(
final
ConfigFileChangeListener
listener
:
m_listeners
)
{
m_executorService
.
submit
(
new
Runnable
()
{
@Override
public
void
run
()
{
String
listenerName
=
listener
.
getClass
().
getName
();
Transaction
transaction
=
Tracer
.
newTransaction
(
"Apollo.ConfigFileChangeListener"
,
listenerName
);
try
{
listener
.
onChange
(
changeEvent
);
transaction
.
setStatus
(
Transaction
.
SUCCESS
);
}
catch
(
Throwable
ex
)
{
transaction
.
setStatus
(
ex
);
Tracer
.
logError
(
ex
);
logger
.
error
(
"Failed to invoke config file change listener {}"
,
listenerName
,
ex
);
}
finally
{
transaction
.
complete
();
}
}
});
}
}
}
apollo-client/src/main/java/com/ctrip/framework/apollo/internals/PlainTextConfigFile.java
View file @
b9fca2d9
package
com
.
ctrip
.
framework
.
apollo
.
internals
;
import
com.ctrip.framework.apollo.core.ConfigConsts
;
import
java.util.Properties
;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public
abstract
class
PlainTextConfigFile
extends
AbstractConfigFile
{
public
PlainTextConfigFile
(
String
namespace
,
ConfigRepository
configRepository
)
{
super
(
namespace
,
configRepository
);
}
...
...
@@ -25,4 +27,9 @@ public abstract class PlainTextConfigFile extends AbstractConfigFile {
}
return
m_configProperties
.
get
().
containsKey
(
ConfigConsts
.
CONFIG_FILE_CONTENT_KEY
);
}
@Override
protected
void
update
(
Properties
newProperties
)
{
m_configProperties
.
set
(
newProperties
);
}
}
apollo-client/src/main/java/com/ctrip/framework/apollo/internals/PropertiesConfigFile.java
View file @
b9fca2d9
...
...
@@ -26,6 +26,12 @@ public class PropertiesConfigFile extends AbstractConfigFile {
}
@Override
protected
void
update
(
Properties
newProperties
)
{
m_configProperties
.
set
(
newProperties
);
m_contentCache
.
set
(
null
);
}
@Override
public
String
getContent
()
{
if
(
m_contentCache
.
get
()
==
null
)
{
m_contentCache
.
set
(
doGetContent
());
...
...
@@ -60,9 +66,4 @@ public class PropertiesConfigFile extends AbstractConfigFile {
return
ConfigFileFormat
.
Properties
;
}
@Override
public
synchronized
void
onRepositoryChange
(
String
namespace
,
Properties
newProperties
)
{
super
.
onRepositoryChange
(
namespace
,
newProperties
);
m_contentCache
.
set
(
null
);
}
}
apollo-client/src/main/java/com/ctrip/framework/apollo/model/ConfigFileChangeEvent.java
0 → 100644
View file @
b9fca2d9
package
com
.
ctrip
.
framework
.
apollo
.
model
;
import
com.ctrip.framework.apollo.enums.PropertyChangeType
;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public
class
ConfigFileChangeEvent
{
private
final
String
namespace
;
private
final
String
oldValue
;
private
final
String
newValue
;
private
final
PropertyChangeType
changeType
;
/**
* Constructor.
*
* @param namespace the namespace of the config file change event
* @param oldValue the value before change
* @param newValue the value after change
* @param changeType the change type
*/
public
ConfigFileChangeEvent
(
String
namespace
,
String
oldValue
,
String
newValue
,
PropertyChangeType
changeType
)
{
this
.
namespace
=
namespace
;
this
.
oldValue
=
oldValue
;
this
.
newValue
=
newValue
;
this
.
changeType
=
changeType
;
}
public
String
getNamespace
()
{
return
namespace
;
}
public
String
getOldValue
()
{
return
oldValue
;
}
public
String
getNewValue
()
{
return
newValue
;
}
public
PropertyChangeType
getChangeType
()
{
return
changeType
;
}
@Override
public
String
toString
()
{
final
StringBuilder
sb
=
new
StringBuilder
(
"ConfigFileChangeEvent{"
);
sb
.
append
(
"namespace='"
).
append
(
namespace
).
append
(
'\''
);
sb
.
append
(
", oldValue='"
).
append
(
oldValue
).
append
(
'\''
);
sb
.
append
(
", newValue='"
).
append
(
newValue
).
append
(
'\''
);
sb
.
append
(
", changeType="
).
append
(
changeType
);
sb
.
append
(
'}'
);
return
sb
.
toString
();
}
}
apollo-client/src/test/java/com/ctrip/framework/apollo/ConfigServiceTest.java
View file @
b9fca2d9
...
...
@@ -132,6 +132,11 @@ public class ConfigServiceTest {
public
ConfigFileFormat
getConfigFileFormat
()
{
return
m_configFileFormat
;
}
@Override
public
void
addChangeListener
(
ConfigFileChangeListener
listener
)
{
}
}
public
static
class
MockConfigFactory
implements
ConfigFactory
{
...
...
apollo-client/src/test/java/com/ctrip/framework/apollo/internals/DefaultConfigManagerTest.java
View file @
b9fca2d9
...
...
@@ -5,6 +5,7 @@ import static org.junit.Assert.assertEquals;
import
static
org
.
junit
.
Assert
.
assertThat
;
import
static
org
.
mockito
.
Mockito
.
mock
;
import
java.util.Properties
;
import
java.util.Set
;
import
org.junit.Before
;
...
...
@@ -111,6 +112,11 @@ public class DefaultConfigManagerTest {
return
new
AbstractConfigFile
(
namespace
,
someConfigRepository
)
{
@Override
protected
void
update
(
Properties
newProperties
)
{
}
@Override
public
String
getContent
()
{
return
someConfigContent
;
}
...
...
apollo-client/src/test/java/com/ctrip/framework/apollo/internals/PropertiesConfigFileTest.java
View file @
b9fca2d9
...
...
@@ -6,8 +6,14 @@ import static org.junit.Assert.assertNull;
import
static
org
.
junit
.
Assert
.
assertTrue
;
import
static
org
.
mockito
.
Mockito
.
when
;
import
com.ctrip.framework.apollo.ConfigFile
;
import
com.ctrip.framework.apollo.ConfigFileChangeListener
;
import
com.ctrip.framework.apollo.enums.PropertyChangeType
;
import
com.ctrip.framework.apollo.model.ConfigFileChangeEvent
;
import
com.google.common.util.concurrent.SettableFuture
;
import
java.util.Properties
;
import
java.util.concurrent.TimeUnit
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
...
...
@@ -84,10 +90,27 @@ public class PropertiesConfigFileTest {
Properties
anotherProperties
=
new
Properties
();
anotherProperties
.
setProperty
(
someKey
,
anotherValue
);
final
SettableFuture
<
ConfigFileChangeEvent
>
configFileChangeFuture
=
SettableFuture
.
create
();
ConfigFileChangeListener
someListener
=
new
ConfigFileChangeListener
()
{
@Override
public
void
onChange
(
ConfigFileChangeEvent
changeEvent
)
{
configFileChangeFuture
.
set
(
changeEvent
);
}
};
configFile
.
addChangeListener
(
someListener
);
configFile
.
onRepositoryChange
(
someNamespace
,
anotherProperties
);
ConfigFileChangeEvent
changeEvent
=
configFileChangeFuture
.
get
(
500
,
TimeUnit
.
MILLISECONDS
);
assertFalse
(
configFile
.
getContent
().
contains
(
String
.
format
(
"%s=%s"
,
someKey
,
someValue
)));
assertTrue
(
configFile
.
getContent
().
contains
(
String
.
format
(
"%s=%s"
,
someKey
,
anotherValue
)));
assertEquals
(
someNamespace
,
changeEvent
.
getNamespace
());
assertTrue
(
changeEvent
.
getOldValue
().
contains
(
String
.
format
(
"%s=%s"
,
someKey
,
someValue
)));
assertTrue
(
changeEvent
.
getNewValue
().
contains
(
String
.
format
(
"%s=%s"
,
someKey
,
anotherValue
)));
assertEquals
(
PropertyChangeType
.
MODIFIED
,
changeEvent
.
getChangeType
());
}
@Test
...
...
apollo-client/src/test/java/com/ctrip/framework/apollo/internals/XmlConfigFileTest.java
View file @
b9fca2d9
...
...
@@ -6,8 +6,13 @@ import static org.junit.Assert.assertNull;
import
static
org
.
junit
.
Assert
.
assertTrue
;
import
static
org
.
mockito
.
Mockito
.
when
;
import
com.ctrip.framework.apollo.ConfigFileChangeListener
;
import
com.ctrip.framework.apollo.enums.PropertyChangeType
;
import
com.ctrip.framework.apollo.model.ConfigFileChangeEvent
;
import
com.google.common.util.concurrent.SettableFuture
;
import
java.util.Properties
;
import
java.util.concurrent.TimeUnit
;
import
org.junit.Before
;
import
org.junit.Test
;
import
org.junit.runner.RunWith
;
...
...
@@ -85,9 +90,97 @@ public class XmlConfigFileTest {
Properties
anotherProperties
=
new
Properties
();
anotherProperties
.
setProperty
(
key
,
anotherValue
);
final
SettableFuture
<
ConfigFileChangeEvent
>
configFileChangeFuture
=
SettableFuture
.
create
();
ConfigFileChangeListener
someListener
=
new
ConfigFileChangeListener
()
{
@Override
public
void
onChange
(
ConfigFileChangeEvent
changeEvent
)
{
configFileChangeFuture
.
set
(
changeEvent
);
}
};
configFile
.
addChangeListener
(
someListener
);
configFile
.
onRepositoryChange
(
someNamespace
,
anotherProperties
);
ConfigFileChangeEvent
changeEvent
=
configFileChangeFuture
.
get
(
500
,
TimeUnit
.
MILLISECONDS
);
assertEquals
(
anotherValue
,
configFile
.
getContent
());
assertEquals
(
someNamespace
,
changeEvent
.
getNamespace
());
assertEquals
(
someValue
,
changeEvent
.
getOldValue
());
assertEquals
(
anotherValue
,
changeEvent
.
getNewValue
());
assertEquals
(
PropertyChangeType
.
MODIFIED
,
changeEvent
.
getChangeType
());
}
@Test
public
void
testOnRepositoryChangeWithContentAdded
()
throws
Exception
{
Properties
someProperties
=
new
Properties
();
String
key
=
ConfigConsts
.
CONFIG_FILE_CONTENT_KEY
;
String
someValue
=
"someValue"
;
when
(
configRepository
.
getConfig
()).
thenReturn
(
someProperties
);
XmlConfigFile
configFile
=
new
XmlConfigFile
(
someNamespace
,
configRepository
);
assertEquals
(
null
,
configFile
.
getContent
());
Properties
anotherProperties
=
new
Properties
();
anotherProperties
.
setProperty
(
key
,
someValue
);
final
SettableFuture
<
ConfigFileChangeEvent
>
configFileChangeFuture
=
SettableFuture
.
create
();
ConfigFileChangeListener
someListener
=
new
ConfigFileChangeListener
()
{
@Override
public
void
onChange
(
ConfigFileChangeEvent
changeEvent
)
{
configFileChangeFuture
.
set
(
changeEvent
);
}
};
configFile
.
addChangeListener
(
someListener
);
configFile
.
onRepositoryChange
(
someNamespace
,
anotherProperties
);
ConfigFileChangeEvent
changeEvent
=
configFileChangeFuture
.
get
(
500
,
TimeUnit
.
MILLISECONDS
);
assertEquals
(
someValue
,
configFile
.
getContent
());
assertEquals
(
someNamespace
,
changeEvent
.
getNamespace
());
assertEquals
(
null
,
changeEvent
.
getOldValue
());
assertEquals
(
someValue
,
changeEvent
.
getNewValue
());
assertEquals
(
PropertyChangeType
.
ADDED
,
changeEvent
.
getChangeType
());
}
@Test
public
void
testOnRepositoryChangeWithContentDeleted
()
throws
Exception
{
Properties
someProperties
=
new
Properties
();
String
key
=
ConfigConsts
.
CONFIG_FILE_CONTENT_KEY
;
String
someValue
=
"someValue"
;
someProperties
.
setProperty
(
key
,
someValue
);
when
(
configRepository
.
getConfig
()).
thenReturn
(
someProperties
);
XmlConfigFile
configFile
=
new
XmlConfigFile
(
someNamespace
,
configRepository
);
assertEquals
(
someValue
,
configFile
.
getContent
());
Properties
anotherProperties
=
new
Properties
();
final
SettableFuture
<
ConfigFileChangeEvent
>
configFileChangeFuture
=
SettableFuture
.
create
();
ConfigFileChangeListener
someListener
=
new
ConfigFileChangeListener
()
{
@Override
public
void
onChange
(
ConfigFileChangeEvent
changeEvent
)
{
configFileChangeFuture
.
set
(
changeEvent
);
}
};
configFile
.
addChangeListener
(
someListener
);
configFile
.
onRepositoryChange
(
someNamespace
,
anotherProperties
);
ConfigFileChangeEvent
changeEvent
=
configFileChangeFuture
.
get
(
500
,
TimeUnit
.
MILLISECONDS
);
assertEquals
(
null
,
configFile
.
getContent
());
assertEquals
(
someNamespace
,
changeEvent
.
getNamespace
());
assertEquals
(
someValue
,
changeEvent
.
getOldValue
());
assertEquals
(
null
,
changeEvent
.
getNewValue
());
assertEquals
(
PropertyChangeType
.
DELETED
,
changeEvent
.
getChangeType
());
}
@Test
...
...
apollo-demo/src/main/java/com/ctrip/framework/apollo/demo/api/ApolloConfigDemo.java
View file @
b9fca2d9
...
...
@@ -5,10 +5,12 @@ import com.google.common.base.Charsets;
import
com.ctrip.framework.apollo.Config
;
import
com.ctrip.framework.apollo.ConfigChangeListener
;
import
com.ctrip.framework.apollo.ConfigFile
;
import
com.ctrip.framework.apollo.ConfigFileChangeListener
;
import
com.ctrip.framework.apollo.ConfigService
;
import
com.ctrip.framework.apollo.core.enums.ConfigFileFormat
;
import
com.ctrip.framework.apollo.model.ConfigChange
;
import
com.ctrip.framework.apollo.model.ConfigChangeEvent
;
import
com.ctrip.framework.apollo.model.ConfigFileChangeEvent
;
import
com.ctrip.framework.foundation.Foundation
;
import
org.slf4j.Logger
;
...
...
@@ -48,6 +50,12 @@ public class ApolloConfigDemo {
publicConfig
.
addChangeListener
(
changeListener
);
applicationConfigFile
=
ConfigService
.
getConfigFile
(
"application"
,
ConfigFileFormat
.
Properties
);
xmlConfigFile
=
ConfigService
.
getConfigFile
(
"datasources"
,
ConfigFileFormat
.
XML
);
xmlConfigFile
.
addChangeListener
(
new
ConfigFileChangeListener
()
{
@Override
public
void
onChange
(
ConfigFileChangeEvent
changeEvent
)
{
logger
.
info
(
changeEvent
.
toString
());
}
});
}
private
String
getConfig
(
String
key
)
{
...
...
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