From 6ace1440e578363db8a41f7fb43c7a4e2d4eb85b Mon Sep 17 00:00:00 2001 From: liuchunlei Date: Thu, 30 May 2019 11:21:41 +0800 Subject: [PATCH] client's SPI for customizing spring processors' loading --- .../annotation/ApolloConfigRegistrar.java | 39 +++----------- .../ConfigPropertySourcesProcessor.java | 38 ++------------ .../spi/ApolloConfigRegistrarHelper.java | 10 ++++ .../ConfigPropertySourcesProcessorHelper.java | 10 ++++ .../DefaultApolloConfigRegistrarHelper.java | 51 +++++++++++++++++++ ...tConfigPropertySourcesProcessorHelper.java | 50 ++++++++++++++++++ ...llo.spring.spi.ApolloConfigRegistrarHelper | 1 + ...g.spi.ConfigPropertySourcesProcessorHelper | 1 + .../spi/ApolloConfigRegistrarHelperTest.java | 22 ++++++++ ...figPropertySourcesProcessorHelperTest.java | 22 ++++++++ .../spring/spi/TestProcessorHelper.java | 18 +++++++ .../spring/spi/TestRegistrarHelper.java | 18 +++++++ ...llo.spring.spi.ApolloConfigRegistrarHelper | 1 + ...g.spi.ConfigPropertySourcesProcessorHelper | 1 + .../internals/ServiceBootstrap.java | 32 ++++++++++++ .../internals/ServiceBootstrapTest.java | 32 ++++++++++++ ....internals.ServiceBootstrapTest$Interface6 | 2 + ....internals.ServiceBootstrapTest$Interface7 | 0 18 files changed, 282 insertions(+), 66 deletions(-) create mode 100644 apollo-client/src/main/java/com/ctrip/framework/apollo/spring/spi/ApolloConfigRegistrarHelper.java create mode 100644 apollo-client/src/main/java/com/ctrip/framework/apollo/spring/spi/ConfigPropertySourcesProcessorHelper.java create mode 100644 apollo-client/src/main/java/com/ctrip/framework/apollo/spring/spi/DefaultApolloConfigRegistrarHelper.java create mode 100644 apollo-client/src/main/java/com/ctrip/framework/apollo/spring/spi/DefaultConfigPropertySourcesProcessorHelper.java create mode 100644 apollo-client/src/main/resources/META-INF/services/com.ctrip.framework.apollo.spring.spi.ApolloConfigRegistrarHelper create mode 100644 apollo-client/src/main/resources/META-INF/services/com.ctrip.framework.apollo.spring.spi.ConfigPropertySourcesProcessorHelper create mode 100644 apollo-client/src/test/java/com/ctrip/framework/apollo/spring/spi/ApolloConfigRegistrarHelperTest.java create mode 100644 apollo-client/src/test/java/com/ctrip/framework/apollo/spring/spi/ConfigPropertySourcesProcessorHelperTest.java create mode 100644 apollo-client/src/test/java/com/ctrip/framework/apollo/spring/spi/TestProcessorHelper.java create mode 100644 apollo-client/src/test/java/com/ctrip/framework/apollo/spring/spi/TestRegistrarHelper.java create mode 100644 apollo-client/src/test/resources/META-INF/services/com.ctrip.framework.apollo.spring.spi.ApolloConfigRegistrarHelper create mode 100644 apollo-client/src/test/resources/META-INF/services/com.ctrip.framework.apollo.spring.spi.ConfigPropertySourcesProcessorHelper create mode 100644 apollo-core/src/test/resources/META-INF/services/com.ctrip.framework.foundation.internals.ServiceBootstrapTest$Interface6 create mode 100644 apollo-core/src/test/resources/META-INF/services/com.ctrip.framework.foundation.internals.ServiceBootstrapTest$Interface7 diff --git a/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/annotation/ApolloConfigRegistrar.java b/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/annotation/ApolloConfigRegistrar.java index 78430a5f62f..562866d7aa5 100644 --- a/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/annotation/ApolloConfigRegistrar.java +++ b/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/annotation/ApolloConfigRegistrar.java @@ -1,47 +1,20 @@ package com.ctrip.framework.apollo.spring.annotation; -import com.ctrip.framework.apollo.spring.property.SpringValueDefinitionProcessor; -import java.util.HashMap; -import java.util.Map; +import com.ctrip.framework.apollo.spring.spi.ApolloConfigRegistrarHelper; +import com.ctrip.framework.foundation.internals.ServiceBootstrap; 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; -import com.ctrip.framework.apollo.spring.config.PropertySourcesProcessor; -import com.ctrip.framework.apollo.spring.util.BeanRegistrationUtil; -import com.google.common.collect.Lists; - /** * @author Jason Song(song_s@ctrip.com) */ 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); - - Map propertySourcesPlaceholderPropertyValues = new HashMap<>(); - // to make sure the default PropertySourcesPlaceholderConfigurer's priority is higher than PropertyPlaceholderConfigurer - propertySourcesPlaceholderPropertyValues.put("order", 0); - - BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, PropertySourcesPlaceholderConfigurer.class.getName(), - PropertySourcesPlaceholderConfigurer.class, propertySourcesPlaceholderPropertyValues); - BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, PropertySourcesProcessor.class.getName(), - PropertySourcesProcessor.class); + private ApolloConfigRegistrarHelper helper = ServiceBootstrap.loadPrimary(ApolloConfigRegistrarHelper.class); - BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, ApolloAnnotationProcessor.class.getName(), - ApolloAnnotationProcessor.class); - - BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, SpringValueProcessor.class.getName(), SpringValueProcessor.class); - BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, SpringValueDefinitionProcessor.class.getName(), SpringValueDefinitionProcessor.class); - - BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, ApolloJsonValueProcessor.class.getName(), - ApolloJsonValueProcessor.class); + @Override + public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { + helper.registerBeanDefinitions(importingClassMetadata, registry); } } diff --git a/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/config/ConfigPropertySourcesProcessor.java b/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/config/ConfigPropertySourcesProcessor.java index 9ab21112756..d997d352ebf 100644 --- a/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/config/ConfigPropertySourcesProcessor.java +++ b/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/config/ConfigPropertySourcesProcessor.java @@ -1,17 +1,10 @@ package com.ctrip.framework.apollo.spring.config; -import com.ctrip.framework.apollo.spring.annotation.SpringValueProcessor; -import com.ctrip.framework.apollo.spring.property.SpringValueDefinitionProcessor; -import com.ctrip.framework.apollo.spring.annotation.ApolloJsonValueProcessor; -import java.util.HashMap; -import java.util.Map; +import com.ctrip.framework.apollo.spring.spi.ConfigPropertySourcesProcessorHelper; +import com.ctrip.framework.foundation.internals.ServiceBootstrap; 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; - -import com.ctrip.framework.apollo.spring.annotation.ApolloAnnotationProcessor; -import com.ctrip.framework.apollo.spring.util.BeanRegistrationUtil; /** * Apollo Property Sources processor for Spring XML Based Application @@ -21,31 +14,10 @@ public class ConfigPropertySourcesProcessor extends PropertySourcesProcessor implements BeanDefinitionRegistryPostProcessor { + private ConfigPropertySourcesProcessorHelper helper = ServiceBootstrap.loadPrimary(ConfigPropertySourcesProcessorHelper.class); + @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { - Map propertySourcesPlaceholderPropertyValues = new HashMap<>(); - // to make sure the default PropertySourcesPlaceholderConfigurer's priority is higher than PropertyPlaceholderConfigurer - propertySourcesPlaceholderPropertyValues.put("order", 0); - - BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, PropertySourcesPlaceholderConfigurer.class.getName(), - PropertySourcesPlaceholderConfigurer.class, propertySourcesPlaceholderPropertyValues); - BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, ApolloAnnotationProcessor.class.getName(), - ApolloAnnotationProcessor.class); - BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, SpringValueProcessor.class.getName(), SpringValueProcessor.class); - BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, ApolloJsonValueProcessor.class.getName(), - ApolloJsonValueProcessor.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); + helper.postProcessBeanDefinitionRegistry(registry); } } diff --git a/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/spi/ApolloConfigRegistrarHelper.java b/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/spi/ApolloConfigRegistrarHelper.java new file mode 100644 index 00000000000..12442019355 --- /dev/null +++ b/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/spi/ApolloConfigRegistrarHelper.java @@ -0,0 +1,10 @@ +package com.ctrip.framework.apollo.spring.spi; + +import com.ctrip.framework.apollo.core.spi.Ordered; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.core.type.AnnotationMetadata; + +public interface ApolloConfigRegistrarHelper extends Ordered { + + void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry); +} diff --git a/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/spi/ConfigPropertySourcesProcessorHelper.java b/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/spi/ConfigPropertySourcesProcessorHelper.java new file mode 100644 index 00000000000..939e3da51fb --- /dev/null +++ b/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/spi/ConfigPropertySourcesProcessorHelper.java @@ -0,0 +1,10 @@ +package com.ctrip.framework.apollo.spring.spi; + +import com.ctrip.framework.apollo.core.spi.Ordered; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; + +public interface ConfigPropertySourcesProcessorHelper extends Ordered { + + void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException; +} diff --git a/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/spi/DefaultApolloConfigRegistrarHelper.java b/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/spi/DefaultApolloConfigRegistrarHelper.java new file mode 100644 index 00000000000..e25f4a88caf --- /dev/null +++ b/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/spi/DefaultApolloConfigRegistrarHelper.java @@ -0,0 +1,51 @@ +package com.ctrip.framework.apollo.spring.spi; + +import com.ctrip.framework.apollo.core.spi.Ordered; +import com.ctrip.framework.apollo.spring.annotation.ApolloAnnotationProcessor; +import com.ctrip.framework.apollo.spring.annotation.ApolloJsonValueProcessor; +import com.ctrip.framework.apollo.spring.annotation.EnableApolloConfig; +import com.ctrip.framework.apollo.spring.annotation.SpringValueProcessor; +import com.ctrip.framework.apollo.spring.config.PropertySourcesProcessor; +import com.ctrip.framework.apollo.spring.property.SpringValueDefinitionProcessor; +import com.ctrip.framework.apollo.spring.util.BeanRegistrationUtil; +import com.google.common.collect.Lists; +import java.util.HashMap; +import java.util.Map; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; +import org.springframework.core.annotation.AnnotationAttributes; +import org.springframework.core.type.AnnotationMetadata; + +public class DefaultApolloConfigRegistrarHelper implements ApolloConfigRegistrarHelper { + + @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); + + Map propertySourcesPlaceholderPropertyValues = new HashMap<>(); + // to make sure the default PropertySourcesPlaceholderConfigurer's priority is higher than PropertyPlaceholderConfigurer + propertySourcesPlaceholderPropertyValues.put("order", 0); + + BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, PropertySourcesPlaceholderConfigurer.class.getName(), + PropertySourcesPlaceholderConfigurer.class, propertySourcesPlaceholderPropertyValues); + BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, PropertySourcesProcessor.class.getName(), + PropertySourcesProcessor.class); + BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, ApolloAnnotationProcessor.class.getName(), + ApolloAnnotationProcessor.class); + BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, SpringValueProcessor.class.getName(), + SpringValueProcessor.class); + BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, SpringValueDefinitionProcessor.class.getName(), + SpringValueDefinitionProcessor.class); + BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, ApolloJsonValueProcessor.class.getName(), + ApolloJsonValueProcessor.class); + } + + @Override + public int getOrder() { + return Ordered.LOWEST_PRECEDENCE; + } +} diff --git a/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/spi/DefaultConfigPropertySourcesProcessorHelper.java b/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/spi/DefaultConfigPropertySourcesProcessorHelper.java new file mode 100644 index 00000000000..5e95c99e880 --- /dev/null +++ b/apollo-client/src/main/java/com/ctrip/framework/apollo/spring/spi/DefaultConfigPropertySourcesProcessorHelper.java @@ -0,0 +1,50 @@ +package com.ctrip.framework.apollo.spring.spi; + +import com.ctrip.framework.apollo.core.spi.Ordered; +import com.ctrip.framework.apollo.spring.annotation.ApolloAnnotationProcessor; +import com.ctrip.framework.apollo.spring.annotation.ApolloJsonValueProcessor; +import com.ctrip.framework.apollo.spring.annotation.SpringValueProcessor; +import com.ctrip.framework.apollo.spring.property.SpringValueDefinitionProcessor; +import com.ctrip.framework.apollo.spring.util.BeanRegistrationUtil; +import java.util.HashMap; +import java.util.Map; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; + +public class DefaultConfigPropertySourcesProcessorHelper implements ConfigPropertySourcesProcessorHelper { + + @Override + public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { + Map propertySourcesPlaceholderPropertyValues = new HashMap<>(); + // to make sure the default PropertySourcesPlaceholderConfigurer's priority is higher than PropertyPlaceholderConfigurer + propertySourcesPlaceholderPropertyValues.put("order", 0); + + BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, PropertySourcesPlaceholderConfigurer.class.getName(), + PropertySourcesPlaceholderConfigurer.class, propertySourcesPlaceholderPropertyValues); + BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, ApolloAnnotationProcessor.class.getName(), + ApolloAnnotationProcessor.class); + BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, SpringValueProcessor.class.getName(), + SpringValueProcessor.class); + BeanRegistrationUtil.registerBeanDefinitionIfNotExists(registry, ApolloJsonValueProcessor.class.getName(), + ApolloJsonValueProcessor.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); + } + + @Override + public int getOrder() { + return Ordered.LOWEST_PRECEDENCE; + } +} diff --git a/apollo-client/src/main/resources/META-INF/services/com.ctrip.framework.apollo.spring.spi.ApolloConfigRegistrarHelper b/apollo-client/src/main/resources/META-INF/services/com.ctrip.framework.apollo.spring.spi.ApolloConfigRegistrarHelper new file mode 100644 index 00000000000..cb6e900846e --- /dev/null +++ b/apollo-client/src/main/resources/META-INF/services/com.ctrip.framework.apollo.spring.spi.ApolloConfigRegistrarHelper @@ -0,0 +1 @@ +com.ctrip.framework.apollo.spring.spi.DefaultApolloConfigRegistrarHelper diff --git a/apollo-client/src/main/resources/META-INF/services/com.ctrip.framework.apollo.spring.spi.ConfigPropertySourcesProcessorHelper b/apollo-client/src/main/resources/META-INF/services/com.ctrip.framework.apollo.spring.spi.ConfigPropertySourcesProcessorHelper new file mode 100644 index 00000000000..07fd0df3c96 --- /dev/null +++ b/apollo-client/src/main/resources/META-INF/services/com.ctrip.framework.apollo.spring.spi.ConfigPropertySourcesProcessorHelper @@ -0,0 +1 @@ +com.ctrip.framework.apollo.spring.spi.DefaultConfigPropertySourcesProcessorHelper diff --git a/apollo-client/src/test/java/com/ctrip/framework/apollo/spring/spi/ApolloConfigRegistrarHelperTest.java b/apollo-client/src/test/java/com/ctrip/framework/apollo/spring/spi/ApolloConfigRegistrarHelperTest.java new file mode 100644 index 00000000000..1d7f099d283 --- /dev/null +++ b/apollo-client/src/test/java/com/ctrip/framework/apollo/spring/spi/ApolloConfigRegistrarHelperTest.java @@ -0,0 +1,22 @@ +package com.ctrip.framework.apollo.spring.spi; + +import static org.springframework.test.util.AssertionErrors.assertEquals; + +import com.ctrip.framework.apollo.spring.annotation.ApolloConfigRegistrar; +import java.lang.reflect.Field; +import org.junit.Test; +import org.springframework.util.ReflectionUtils; + +public class ApolloConfigRegistrarHelperTest { + + @Test + public void testHelperLoadingOrder() { + ApolloConfigRegistrar apolloConfigRegistrar = new ApolloConfigRegistrar(); + + Field field = ReflectionUtils.findField(ApolloConfigRegistrar.class, "helper"); + ReflectionUtils.makeAccessible(field); + Object helper = ReflectionUtils.getField(field, apolloConfigRegistrar); + + assertEquals("helper is not TestRegistrarHelper instance", TestRegistrarHelper.class, helper.getClass()); + } +} diff --git a/apollo-client/src/test/java/com/ctrip/framework/apollo/spring/spi/ConfigPropertySourcesProcessorHelperTest.java b/apollo-client/src/test/java/com/ctrip/framework/apollo/spring/spi/ConfigPropertySourcesProcessorHelperTest.java new file mode 100644 index 00000000000..fe486526893 --- /dev/null +++ b/apollo-client/src/test/java/com/ctrip/framework/apollo/spring/spi/ConfigPropertySourcesProcessorHelperTest.java @@ -0,0 +1,22 @@ +package com.ctrip.framework.apollo.spring.spi; + +import static org.springframework.test.util.AssertionErrors.assertEquals; + +import com.ctrip.framework.apollo.spring.config.ConfigPropertySourcesProcessor; +import java.lang.reflect.Field; +import org.junit.Test; +import org.springframework.util.ReflectionUtils; + +public class ConfigPropertySourcesProcessorHelperTest { + + @Test + public void testHelperLoadingOrder() { + ConfigPropertySourcesProcessor processor = new ConfigPropertySourcesProcessor(); + + Field field = ReflectionUtils.findField(ConfigPropertySourcesProcessor.class, "helper"); + ReflectionUtils.makeAccessible(field); + Object helper = ReflectionUtils.getField(field, processor); + + assertEquals("helper is not TestProcessorHelper instance", TestProcessorHelper.class, helper.getClass()); + } +} diff --git a/apollo-client/src/test/java/com/ctrip/framework/apollo/spring/spi/TestProcessorHelper.java b/apollo-client/src/test/java/com/ctrip/framework/apollo/spring/spi/TestProcessorHelper.java new file mode 100644 index 00000000000..a80952f58ec --- /dev/null +++ b/apollo-client/src/test/java/com/ctrip/framework/apollo/spring/spi/TestProcessorHelper.java @@ -0,0 +1,18 @@ +package com.ctrip.framework.apollo.spring.spi; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.support.BeanDefinitionRegistry; + +public class TestProcessorHelper extends DefaultConfigPropertySourcesProcessorHelper { + + @Override + public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) + throws BeansException { + super.postProcessBeanDefinitionRegistry(registry); + } + + @Override + public int getOrder() { + return 0; + } +} diff --git a/apollo-client/src/test/java/com/ctrip/framework/apollo/spring/spi/TestRegistrarHelper.java b/apollo-client/src/test/java/com/ctrip/framework/apollo/spring/spi/TestRegistrarHelper.java new file mode 100644 index 00000000000..26285470a73 --- /dev/null +++ b/apollo-client/src/test/java/com/ctrip/framework/apollo/spring/spi/TestRegistrarHelper.java @@ -0,0 +1,18 @@ +package com.ctrip.framework.apollo.spring.spi; + +import org.springframework.beans.factory.support.BeanDefinitionRegistry; +import org.springframework.core.type.AnnotationMetadata; + +public class TestRegistrarHelper extends DefaultApolloConfigRegistrarHelper { + + @Override + public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, + BeanDefinitionRegistry registry) { + super.registerBeanDefinitions(importingClassMetadata, registry); + } + + @Override + public int getOrder() { + return 0; + } +} diff --git a/apollo-client/src/test/resources/META-INF/services/com.ctrip.framework.apollo.spring.spi.ApolloConfigRegistrarHelper b/apollo-client/src/test/resources/META-INF/services/com.ctrip.framework.apollo.spring.spi.ApolloConfigRegistrarHelper new file mode 100644 index 00000000000..b51082c31b6 --- /dev/null +++ b/apollo-client/src/test/resources/META-INF/services/com.ctrip.framework.apollo.spring.spi.ApolloConfigRegistrarHelper @@ -0,0 +1 @@ +com.ctrip.framework.apollo.spring.spi.TestRegistrarHelper diff --git a/apollo-client/src/test/resources/META-INF/services/com.ctrip.framework.apollo.spring.spi.ConfigPropertySourcesProcessorHelper b/apollo-client/src/test/resources/META-INF/services/com.ctrip.framework.apollo.spring.spi.ConfigPropertySourcesProcessorHelper new file mode 100644 index 00000000000..64d7bb6109e --- /dev/null +++ b/apollo-client/src/test/resources/META-INF/services/com.ctrip.framework.apollo.spring.spi.ConfigPropertySourcesProcessorHelper @@ -0,0 +1 @@ +com.ctrip.framework.apollo.spring.spi.TestProcessorHelper diff --git a/apollo-core/src/main/java/com/ctrip/framework/foundation/internals/ServiceBootstrap.java b/apollo-core/src/main/java/com/ctrip/framework/foundation/internals/ServiceBootstrap.java index a34a518cfab..4ae8bbba7e1 100644 --- a/apollo-core/src/main/java/com/ctrip/framework/foundation/internals/ServiceBootstrap.java +++ b/apollo-core/src/main/java/com/ctrip/framework/foundation/internals/ServiceBootstrap.java @@ -1,6 +1,11 @@ package com.ctrip.framework.foundation.internals; +import com.ctrip.framework.apollo.core.spi.Ordered; +import com.google.common.collect.Lists; +import java.util.Collections; +import java.util.Comparator; import java.util.Iterator; +import java.util.List; import java.util.ServiceLoader; public class ServiceBootstrap { @@ -19,4 +24,31 @@ public static Iterator loadAll(Class clazz) { return loader.iterator(); } + + public static List loadAllOrdered(Class clazz) { + Iterator iterator = loadAll(clazz); + + if (!iterator.hasNext()) { + throw new IllegalStateException(String.format( + "No implementation defined in /META-INF/services/%s, please check whether the file exists and has the right implementation class!", + clazz.getName())); + } + + List candidates = Lists.newArrayList(iterator); + Collections.sort(candidates, new Comparator() { + @Override + public int compare(S o1, S o2) { + // the smaller order has higher priority + return Integer.compare(o1.getOrder(), o2.getOrder()); + } + }); + + return candidates; + } + + public static S loadPrimary(Class clazz) { + List candidates = loadAllOrdered(clazz); + + return candidates.get(0); + } } diff --git a/apollo-core/src/test/java/com/ctrip/framework/foundation/internals/ServiceBootstrapTest.java b/apollo-core/src/test/java/com/ctrip/framework/foundation/internals/ServiceBootstrapTest.java index b3b8ed617c3..620da7d0c5b 100644 --- a/apollo-core/src/test/java/com/ctrip/framework/foundation/internals/ServiceBootstrapTest.java +++ b/apollo-core/src/test/java/com/ctrip/framework/foundation/internals/ServiceBootstrapTest.java @@ -1,5 +1,6 @@ package com.ctrip.framework.foundation.internals; +import com.ctrip.framework.apollo.core.spi.Ordered; import org.junit.Test; import java.util.ServiceConfigurationError; @@ -36,6 +37,17 @@ public void loadFirstWithServiceImplNotExists() throws Exception { ServiceBootstrap.loadFirst(Interface5.class); } + @Test + public void loadPrimarySuccessfully() { + Interface6 service = ServiceBootstrap.loadPrimary(Interface6.class); + assertTrue(service instanceof Interface6Impl1); + } + + @Test(expected = IllegalStateException.class) + public void loadPrimaryWithServiceFileButNoServiceImpl() { + ServiceBootstrap.loadPrimary(Interface7.class); + } + private interface Interface1 { } @@ -53,4 +65,24 @@ private interface Interface4 { private interface Interface5 { } + + private interface Interface6 extends Ordered { + } + + public static class Interface6Impl1 implements Interface6 { + @Override + public int getOrder() { + return 1; + } + } + + public static class Interface6Impl2 implements Interface6 { + @Override + public int getOrder() { + return 2; + } + } + + private interface Interface7 extends Ordered { + } } diff --git a/apollo-core/src/test/resources/META-INF/services/com.ctrip.framework.foundation.internals.ServiceBootstrapTest$Interface6 b/apollo-core/src/test/resources/META-INF/services/com.ctrip.framework.foundation.internals.ServiceBootstrapTest$Interface6 new file mode 100644 index 00000000000..7041108b20f --- /dev/null +++ b/apollo-core/src/test/resources/META-INF/services/com.ctrip.framework.foundation.internals.ServiceBootstrapTest$Interface6 @@ -0,0 +1,2 @@ +com.ctrip.framework.foundation.internals.ServiceBootstrapTest$Interface6Impl1 +com.ctrip.framework.foundation.internals.ServiceBootstrapTest$Interface6Impl2 diff --git a/apollo-core/src/test/resources/META-INF/services/com.ctrip.framework.foundation.internals.ServiceBootstrapTest$Interface7 b/apollo-core/src/test/resources/META-INF/services/com.ctrip.framework.foundation.internals.ServiceBootstrapTest$Interface7 new file mode 100644 index 00000000000..e69de29bb2d