-
-
Notifications
You must be signed in to change notification settings - Fork 10.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #543 from nobodyiam/client-spring-integration
Client spring integration
- Loading branch information
Showing
54 changed files
with
1,880 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
83 changes: 83 additions & 0 deletions
83
...src/main/java/com/ctrip/framework/apollo/spring/annotation/ApolloAnnotationProcessor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
package com.ctrip.framework.apollo.spring.annotation; | ||
|
||
import com.google.common.base.Preconditions; | ||
|
||
import com.ctrip.framework.apollo.Config; | ||
import com.ctrip.framework.apollo.ConfigChangeListener; | ||
import com.ctrip.framework.apollo.ConfigService; | ||
import com.ctrip.framework.apollo.model.ConfigChangeEvent; | ||
|
||
import org.springframework.beans.BeansException; | ||
import org.springframework.beans.factory.config.BeanPostProcessor; | ||
import org.springframework.core.annotation.AnnotationUtils; | ||
import org.springframework.util.ReflectionUtils; | ||
|
||
import java.lang.reflect.Field; | ||
import java.lang.reflect.Method; | ||
|
||
/** | ||
* Apollo Annotation Processor for Spring Application | ||
* | ||
* @author Jason Song([email protected]) | ||
*/ | ||
public class ApolloAnnotationProcessor implements BeanPostProcessor { | ||
@Override | ||
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { | ||
Class clazz = bean.getClass(); | ||
processFields(bean, clazz.getDeclaredFields()); | ||
processMethods(bean, clazz.getDeclaredMethods()); | ||
return bean; | ||
} | ||
|
||
@Override | ||
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { | ||
return bean; | ||
} | ||
|
||
private void processFields(Object bean, Field[] declaredFields) { | ||
for (Field field : declaredFields) { | ||
ApolloConfig annotation = AnnotationUtils.getAnnotation(field, ApolloConfig.class); | ||
if (annotation == null) { | ||
continue; | ||
} | ||
|
||
Preconditions.checkArgument(Config.class.isAssignableFrom(field.getType()), | ||
"Invalid type: %s for field: %s, should be Config", field.getType(), field); | ||
|
||
String namespace = annotation.value(); | ||
Config config = ConfigService.getConfig(namespace); | ||
|
||
ReflectionUtils.makeAccessible(field); | ||
ReflectionUtils.setField(field, bean, config); | ||
} | ||
} | ||
|
||
private void processMethods(final Object bean, Method[] declaredMethods) { | ||
for (final Method method : declaredMethods) { | ||
ApolloConfigChangeListener annotation = AnnotationUtils.findAnnotation(method, ApolloConfigChangeListener.class); | ||
if (annotation == null) { | ||
continue; | ||
} | ||
|
||
Class<?>[] parameterTypes = method.getParameterTypes(); | ||
Preconditions.checkArgument(parameterTypes.length == 1, | ||
"Invalid number of parameters: %s for method: %s, should be 1", parameterTypes.length, method); | ||
Preconditions.checkArgument(ConfigChangeEvent.class.isAssignableFrom(parameterTypes[0]), | ||
"Invalid parameter type: %s for method: %s, should be ConfigChangeEvent", parameterTypes[0], method); | ||
|
||
ReflectionUtils.makeAccessible(method); | ||
String[] namespaces = annotation.value(); | ||
for (String namespace : namespaces) { | ||
Config config = ConfigService.getConfig(namespace); | ||
|
||
config.addChangeListener(new ConfigChangeListener() { | ||
@Override | ||
public void onChange(ConfigChangeEvent changeEvent) { | ||
ReflectionUtils.invokeMethod(method, bean, changeEvent); | ||
} | ||
}); | ||
} | ||
} | ||
} | ||
|
||
} |
31 changes: 31 additions & 0 deletions
31
apollo-client/src/main/java/com/ctrip/framework/apollo/spring/annotation/ApolloConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package com.ctrip.framework.apollo.spring.annotation; | ||
|
||
import com.ctrip.framework.apollo.core.ConfigConsts; | ||
|
||
import java.lang.annotation.Documented; | ||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
/** | ||
* Use this annotation to inject Apollo Config Instance. | ||
* | ||
* <p>Usage example:</p> | ||
* <pre class="code"> | ||
* //Inject the config for "someNamespace" | ||
* @ApolloConfig("someNamespace") | ||
* private Config config; | ||
* </pre> | ||
* | ||
* @author Jason Song([email protected]) | ||
*/ | ||
@Retention(RetentionPolicy.RUNTIME) | ||
@Target(ElementType.FIELD) | ||
@Documented | ||
public @interface ApolloConfig { | ||
/** | ||
* Apollo namespace for the config, if not specified then default to application | ||
*/ | ||
String value() default ConfigConsts.NAMESPACE_APPLICATION; | ||
} |
33 changes: 33 additions & 0 deletions
33
...rc/main/java/com/ctrip/framework/apollo/spring/annotation/ApolloConfigChangeListener.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package com.ctrip.framework.apollo.spring.annotation; | ||
|
||
import com.ctrip.framework.apollo.core.ConfigConsts; | ||
|
||
import java.lang.annotation.Documented; | ||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
/** | ||
* Use this annotation to register Apollo ConfigChangeListener. | ||
* | ||
* <p>Usage example:</p> | ||
* <pre class="code"> | ||
* //Listener on namespaces of "someNamespace" and "anotherNamespace" | ||
* @ApolloConfigChangeListener({"someNamespace","anotherNamespace"}) | ||
* private void onChange(ConfigChangeEvent changeEvent) { | ||
* //handle change event | ||
* } | ||
* </pre> | ||
* | ||
* @author Jason Song([email protected]) | ||
*/ | ||
@Retention(RetentionPolicy.RUNTIME) | ||
@Target(ElementType.METHOD) | ||
@Documented | ||
public @interface ApolloConfigChangeListener { | ||
/** | ||
* Apollo namespace for the config, if not specified then default to application | ||
*/ | ||
String[] value() default {ConfigConsts.NAMESPACE_APPLICATION}; | ||
} |
35 changes: 35 additions & 0 deletions
35
...ent/src/main/java/com/ctrip/framework/apollo/spring/annotation/ApolloConfigRegistrar.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package com.ctrip.framework.apollo.spring.annotation; | ||
|
||
import com.google.common.collect.Lists; | ||
|
||
import com.ctrip.framework.apollo.spring.config.PropertySourcesProcessor; | ||
import com.ctrip.framework.apollo.spring.util.BeanRegistrationUtil; | ||
|
||
import org.springframework.beans.factory.support.BeanDefinitionRegistry; | ||
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; | ||
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; | ||
import org.springframework.core.annotation.AnnotationAttributes; | ||
import org.springframework.core.type.AnnotationMetadata; | ||
|
||
/** | ||
* @author Jason Song([email protected]) | ||
*/ | ||
public class ApolloConfigRegistrar implements ImportBeanDefinitionRegistrar { | ||
@Override | ||
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { | ||
AnnotationAttributes attributes = AnnotationAttributes.fromMap(importingClassMetadata | ||
.getAnnotationAttributes(EnableApolloConfig.class.getName())); | ||
String[] namespaces = attributes.getStringArray("value"); | ||
int order = attributes.getNumber("order"); | ||
PropertySourcesProcessor.addNamespaces(Lists.newArrayList(namespaces), order); | ||
|
||
BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, PropertySourcesPlaceholderConfigurer.class.getName(), | ||
PropertySourcesPlaceholderConfigurer.class); | ||
|
||
BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, PropertySourcesProcessor.class.getName(), | ||
PropertySourcesProcessor.class); | ||
|
||
BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, ApolloAnnotationProcessor.class.getName(), | ||
ApolloAnnotationProcessor.class); | ||
} | ||
} |
44 changes: 44 additions & 0 deletions
44
...client/src/main/java/com/ctrip/framework/apollo/spring/annotation/EnableApolloConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
package com.ctrip.framework.apollo.spring.annotation; | ||
|
||
import com.ctrip.framework.apollo.core.ConfigConsts; | ||
|
||
import org.springframework.context.annotation.Import; | ||
import org.springframework.core.Ordered; | ||
|
||
import java.lang.annotation.Documented; | ||
import java.lang.annotation.ElementType; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
import java.lang.annotation.Target; | ||
|
||
/** | ||
* Use this annotation to register Apollo property sources when using Java Config. | ||
* | ||
* <p>Configuration example:</p> | ||
* <pre class="code"> | ||
* @Configuration | ||
* @EnableApolloConfig({"someNamespace","anotherNamespace"}) | ||
* public class AppConfig { | ||
* | ||
* } | ||
* </pre> | ||
* | ||
* @author Jason Song([email protected]) | ||
*/ | ||
@Retention(RetentionPolicy.RUNTIME) | ||
@Target(ElementType.TYPE) | ||
@Documented | ||
@Import(ApolloConfigRegistrar.class) | ||
public @interface EnableApolloConfig { | ||
/** | ||
* Apollo namespaces to inject configuration into Spring Property Sources. | ||
*/ | ||
String[] value() default {ConfigConsts.NAMESPACE_APPLICATION}; | ||
|
||
/** | ||
* The order of the apollo config, default is {@link Ordered#LOWEST_PRECEDENCE}, which is Integer.MAX_VALUE. | ||
* If there are properties with the same name in different apollo configs, the apollo config with smaller order wins. | ||
* @return | ||
*/ | ||
int order() default Ordered.LOWEST_PRECEDENCE; | ||
} |
21 changes: 21 additions & 0 deletions
21
...o-client/src/main/java/com/ctrip/framework/apollo/spring/config/ConfigPropertySource.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package com.ctrip.framework.apollo.spring.config; | ||
|
||
import com.ctrip.framework.apollo.Config; | ||
|
||
import org.springframework.core.env.PropertySource; | ||
|
||
/** | ||
* Property source wrapper for Config | ||
* | ||
* @author Jason Song([email protected]) | ||
*/ | ||
public class ConfigPropertySource extends PropertySource<Config> { | ||
public ConfigPropertySource(String name, Config source) { | ||
super(name, source); | ||
} | ||
|
||
@Override | ||
public Object getProperty(String name) { | ||
return this.source.getProperty(name, null); | ||
} | ||
} |
26 changes: 26 additions & 0 deletions
26
...rc/main/java/com/ctrip/framework/apollo/spring/config/ConfigPropertySourcesProcessor.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package com.ctrip.framework.apollo.spring.config; | ||
|
||
import com.ctrip.framework.apollo.spring.annotation.ApolloAnnotationProcessor; | ||
import com.ctrip.framework.apollo.spring.util.BeanRegistrationUtil; | ||
|
||
import org.springframework.beans.BeansException; | ||
import org.springframework.beans.factory.support.BeanDefinitionRegistry; | ||
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; | ||
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; | ||
|
||
/** | ||
* Apollo Property Sources processor for Spring XML Based Application | ||
* | ||
* @author Jason Song([email protected]) | ||
*/ | ||
public class ConfigPropertySourcesProcessor extends PropertySourcesProcessor | ||
implements BeanDefinitionRegistryPostProcessor { | ||
|
||
@Override | ||
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { | ||
BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, PropertySourcesPlaceholderConfigurer.class.getName(), | ||
PropertySourcesPlaceholderConfigurer.class); | ||
BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, ApolloAnnotationProcessor.class.getName(), | ||
ApolloAnnotationProcessor.class); | ||
} | ||
} |
58 changes: 58 additions & 0 deletions
58
apollo-client/src/main/java/com/ctrip/framework/apollo/spring/config/NamespaceHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package com.ctrip.framework.apollo.spring.config; | ||
|
||
import com.google.common.base.Splitter; | ||
import com.google.common.base.Strings; | ||
|
||
import com.ctrip.framework.apollo.core.ConfigConsts; | ||
|
||
import org.springframework.beans.factory.support.BeanDefinitionBuilder; | ||
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; | ||
import org.springframework.beans.factory.xml.NamespaceHandlerSupport; | ||
import org.springframework.core.Ordered; | ||
import org.w3c.dom.Element; | ||
|
||
/** | ||
* @author Jason Song([email protected]) | ||
*/ | ||
public class NamespaceHandler extends NamespaceHandlerSupport { | ||
private static final Splitter NAMESPACE_SPLITTER = Splitter.on(",").omitEmptyStrings().trimResults(); | ||
|
||
@Override | ||
public void init() { | ||
registerBeanDefinitionParser("config", new BeanParser()); | ||
} | ||
|
||
static class BeanParser extends AbstractSingleBeanDefinitionParser { | ||
@Override | ||
protected Class<?> getBeanClass(Element element) { | ||
return ConfigPropertySourcesProcessor.class; | ||
} | ||
|
||
@Override | ||
protected boolean shouldGenerateId() { | ||
return true; | ||
} | ||
|
||
@Override | ||
protected void doParse(Element element, BeanDefinitionBuilder builder) { | ||
String namespaces = element.getAttribute("namespaces"); | ||
//default to application | ||
if (Strings.isNullOrEmpty(namespaces)) { | ||
namespaces = ConfigConsts.NAMESPACE_APPLICATION; | ||
} | ||
|
||
int order = Ordered.LOWEST_PRECEDENCE; | ||
String orderAttribute = element.getAttribute("order"); | ||
|
||
if (!Strings.isNullOrEmpty(orderAttribute)) { | ||
try { | ||
order = Integer.parseInt(orderAttribute); | ||
} catch (Throwable ex) { | ||
throw new IllegalArgumentException( | ||
String.format("Invalid order: %s for namespaces: %s", orderAttribute, namespaces)); | ||
} | ||
} | ||
PropertySourcesProcessor.addNamespaces(NAMESPACE_SPLITTER.splitToList(namespaces), order); | ||
} | ||
} | ||
} |
Oops, something went wrong.