提交 1f5b3648 编写于 作者: J Jason Song

Allow users to inject customized instance via ApolloInjectorCustomizer

上级 d0597959
package com.ctrip.framework.apollo.internals;
import com.ctrip.framework.apollo.exceptions.ApolloConfigException;
import com.ctrip.framework.apollo.spi.ApolloInjectorCustomizer;
import com.ctrip.framework.apollo.spi.ConfigFactory;
import com.ctrip.framework.apollo.spi.ConfigFactoryManager;
import com.ctrip.framework.apollo.spi.ConfigRegistry;
......@@ -14,20 +15,24 @@ import com.ctrip.framework.apollo.util.factory.PropertiesFactory;
import com.ctrip.framework.apollo.util.http.HttpUtil;
import com.ctrip.framework.apollo.util.yaml.YamlParser;
import com.ctrip.framework.foundation.internals.ServiceBootstrap;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Singleton;
import java.util.List;
/**
* Guice injector
* @author Jason Song(song_s@ctrip.com)
*/
public class DefaultInjector implements Injector {
private com.google.inject.Injector m_injector;
private final com.google.inject.Injector m_injector;
private final List<ApolloInjectorCustomizer> m_customizers;
public DefaultInjector() {
try {
m_injector = Guice.createInjector(new ApolloModule());
m_customizers = ServiceBootstrap.loadAllOrdered(ApolloInjectorCustomizer.class);
} catch (Throwable ex) {
ApolloConfigException exception = new ApolloConfigException("Unable to initialize Guice Injector!", ex);
Tracer.logError(exception);
......@@ -38,6 +43,12 @@ public class DefaultInjector implements Injector {
@Override
public <T> T getInstance(Class<T> clazz) {
try {
for (ApolloInjectorCustomizer customizer : m_customizers) {
T instance = customizer.getInstance(clazz);
if (instance != null) {
return instance;
}
}
return m_injector.getInstance(clazz);
} catch (Throwable ex) {
Tracer.logError(ex);
......@@ -48,8 +59,20 @@ public class DefaultInjector implements Injector {
@Override
public <T> T getInstance(Class<T> clazz, String name) {
//Guice does not support get instance by type and name
return null;
try {
for (ApolloInjectorCustomizer customizer : m_customizers) {
T instance = customizer.getInstance(clazz, name);
if (instance != null) {
return instance;
}
}
//Guice does not support get instance by type and name
return null;
} catch (Throwable ex) {
Tracer.logError(ex);
throw new ApolloConfigException(
String.format("Unable to load instance for %s with name %s!", clazz.getName(), name), ex);
}
}
private static class ApolloModule extends AbstractModule {
......
package com.ctrip.framework.apollo.spi;
import com.ctrip.framework.apollo.core.spi.Ordered;
import com.ctrip.framework.apollo.internals.DefaultInjector;
import com.ctrip.framework.apollo.internals.Injector;
/**
* Allow users to inject customized instances, see {@link DefaultInjector#getInstance(java.lang.Class)}
*/
public interface ApolloInjectorCustomizer extends Injector, Ordered {
}
package com.ctrip.framework.apollo.build;
import java.util.Map;
import com.ctrip.framework.apollo.internals.DefaultInjector;
import com.ctrip.framework.apollo.internals.Injector;
import com.ctrip.framework.apollo.spi.ApolloInjectorCustomizer;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Maps;
import com.google.common.collect.Table;
import java.util.Map;
/**
* @author Jason Song(song_s@ctrip.com)
*/
public class MockInjector implements Injector {
private static Map<Class, Object> classMap = Maps.newHashMap();
private static Table<Class, String, Object> classTable = HashBasedTable.create();
private static Injector delegate = new DefaultInjector();
@Override
public <T> T getInstance(Class<T> clazz) {
T o = (T) classMap.get(clazz);
if (o != null) {
return o;
}
if (delegate != null) {
return delegate.getInstance(clazz);
}
......@@ -32,11 +28,6 @@ public class MockInjector implements Injector {
@Override
public <T> T getInstance(Class<T> clazz, String name) {
T o = (T) classTable.get(clazz, name);
if (o != null) {
return o;
}
if (delegate != null) {
return delegate.getInstance(clazz, name);
}
......@@ -61,4 +52,22 @@ public class MockInjector implements Injector {
classTable.clear();
delegate = new DefaultInjector();
}
public static class InjectCustomizer implements ApolloInjectorCustomizer {
@Override
public <T> T getInstance(Class<T> clazz) {
return (T) classMap.get(clazz);
}
@Override
public <T> T getInstance(Class<T> clazz, String name) {
return (T) classTable.get(clazz, name);
}
@Override
public int getOrder() {
return 0;
}
}
}
com.ctrip.framework.apollo.build.MockInjector$InjectCustomizer
\ No newline at end of file
......@@ -27,13 +27,6 @@ public class ServiceBootstrap {
public static <S extends Ordered> List<S> loadAllOrdered(Class<S> clazz) {
Iterator<S> 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<S> candidates = Lists.newArrayList(iterator);
Collections.sort(candidates, new Comparator<S>() {
@Override
......@@ -49,6 +42,13 @@ public class ServiceBootstrap {
public static <S extends Ordered> S loadPrimary(Class<S> clazz) {
List<S> candidates = loadAllOrdered(clazz);
if (candidates.isEmpty()) {
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()));
}
return candidates.get(0);
}
}
......@@ -5,6 +5,7 @@ import org.junit.Test;
import java.util.ServiceConfigurationError;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
/**
......@@ -37,6 +38,11 @@ public class ServiceBootstrapTest {
ServiceBootstrap.loadFirst(Interface5.class);
}
@Test
public void loadAllWithServiceFileButNoServiceImpl() {
assertFalse(ServiceBootstrap.loadAll(Interface7.class).hasNext());
}
@Test
public void loadPrimarySuccessfully() {
Interface6 service = ServiceBootstrap.loadPrimary(Interface6.class);
......@@ -48,6 +54,11 @@ public class ServiceBootstrapTest {
ServiceBootstrap.loadPrimary(Interface7.class);
}
@Test
public void loadAllOrderedWithServiceFileButNoServiceImpl() {
assertTrue(ServiceBootstrap.loadAllOrdered(Interface7.class).isEmpty());
}
interface Interface1 {
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册