本文会讲解apollo客户端如何读取基础配置的,顺带手讲解SPI机制。
我们定位到Foundation类,Foundation类有一个静态代码块,
static {
getManager();
}
private static ProviderManager getManager() {
try {
if (s_manager == null) {
// Double locking to make sure only one thread initializes ProviderManager.
synchronized (lock) {
if (s_manager == null) {
s_manager = ServiceBootstrap.loadFirst(ProviderManager.class);
}
}
}
return s_manager;
} catch (Throwable ex) {
s_manager = new NullProviderManager();
logger.error("Initialize ProviderManager failed.", ex);
return s_manager;
}
}
ProviderManager是一个接口,这里的loadFirst方法是运用了SPI机制获取到它的实现类,并进行实例化。
如何才能通过SPI加载实现类
1.需要在META-INF.service路径下添加文本文件,将接口的全名作为文件名,文件内容为实现类的全名:
文件路径
文本文件
2.代码获取实现类
public static <S> S loadFirst(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()));
}
//只取第一个实现类
return iterator.next();
}
public static <S> Iterator<S> loadAll(Class<S> clazz) {
//获取文本文件中所有的实现类对象
ServiceLoader<S> loader = ServiceLoader.load(clazz);
return loader.iterator();
}
loadFirst方法获取到DefaultProviderManager对象。
读取META-INF/app.properties
我们来看下DefaultProviderManager的构造方法
public DefaultProviderManager() {
// Load per-application configuration, like app id, from classpath://META-INF/app.properties
Provider applicationProvider = new DefaultApplicationProvider();
applicationProvider.initialize();
register(applicationProvider);
// Load network parameters
Provider networkProvider = new DefaultNetworkProvider();
networkProvider.initialize();
register(networkProvider);
// Load environment (fat, fws, uat, prod ...) and dc, from /opt/settings/server.properties, JVM property and/or OS
// environment variables.
Provider serverProvider = new DefaultServerProvider();
serverProvider.initialize();
register(serverProvider);
}
DefaultApplicationProvider类的initialize方法会读取META-INF/app.properties文件的配置项,并放到Properties中,Properties类继承自Hashtable。我们需要获取地址的时候,从Properties对象中获取key=apollo.meta的值即可。
这里我们需要注意一点,就是apollo的服务器地址和appId一定要放到/META-INF/app.properties里面,路径和文件名是固定的,因为这在apollo代码里写死的。