想要了解springboot加载配置文件,要了解观察者模式,以及相应的实现方式
1、观察者模式(Publish/Subscribe):
举例说明:
报社方负责出版报纸.
你订阅了该报社的报纸,那么只要报社发布了新报纸,就会通知你,或发到你手上.
如果你不想再读报纸,可以取消订阅,这样,报社发布了新报纸就不会再通知你.
jdk不仅提供了Observable类、Observer接口支持观察者模式,而且也提供了EventObject类、EventListener接口来支持事件监听模式,
虽然两者属于同一类型模式,都属于回调机制,主动推送消息,但使用场景有些区别。
1. 事件-监听机制
2. 观察者模式
观察者(Observer)相当于事件监听者(监听器),被观察者(Observable)相当于事件源和事件,执行逻辑时通知observer即可触发oberver的update,
同时 可传被观察者和参数。简化了事件-监听模式的实现
连接为设计模式
package com.ctrip.framework.apollo.configservice;
import com.ctrip.framework.apollo.biz.ApolloBizConfig;
import com.ctrip.framework.apollo.common.ApolloCommonConfig;
import com.ctrip.framework.apollo.metaservice.ApolloMetaServiceConfig;
import java.lang.reflect.Constructor;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.springframework.beans.BeanUtils;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.io.UrlResource;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.springframework.core.io.support.SpringFactoriesLoader;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ConcurrentReferenceHashMap;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
/**
* Spring boot application entry point
*
* @author Jason Song(song_s@ctrip.com)
*/
@EnableEurekaServer
@EnableAspectJAutoProxy
@EnableAutoConfiguration // (exclude = EurekaClientConfigBean.class)
@Configuration
@EnableTransactionManagement
@PropertySource(value = {"classpath:configservice.properties"})
@ComponentScan(basePackageClasses = {ApolloCommonConfig.class,
ApolloBizConfig.class,
ConfigServiceApplication.class,
ApolloMetaServiceConfig.class})
public class ConfigServiceApplication {
private static final Map<ClassLoader, MultiValueMap<String, String>> cache = new ConcurrentReferenceHashMap<>();
public static void main(String[] args) throws Exception {
ClassLoader classloader = ConfigServiceApplication.class.getClassLoader();
Enumeration<URL> urls = classloader.getResources("META-INF/spring.factories") ;
MultiValueMap<String, String> result = new LinkedMultiValueMap<>();
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
UrlResource resource = new UrlResource(url);
Properties properties = PropertiesLoaderUtils.loadProperties(resource);
for (Map.Entry<?, ?> entry : properties.entrySet()) {
List<String> factoryClassNames = Arrays.asList(StringUtils.commaDelimitedListToStringArray((String) entry.getValue()));
result.addAll((String) entry.getKey(), factoryClassNames);
}
}
cache.put(classloader, result);
String factoryClassName = ApplicationContextInitializer.class.getName();
result.getOrDefault(factoryClassName, Collections.emptyList());
Set<String> names = new LinkedHashSet<>(result.getOrDefault(factoryClassName, Collections.emptyList()));
System.out.println(names);
for (String name : names) {
Class<?> instanceClass = ClassUtils.forName(name, classloader);
Assert.isAssignable(ApplicationContextInitializer.class, instanceClass);
Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);
BeanUtils.instantiateClass(constructor, args);
Object instance = (Object) BeanUtils.instantiateClass(constructor, args);
}
SpringApplication.run(ConfigServiceApplication.class, args);
}
@SuppressWarnings("unchecked")
private <T> List<T> createSpringFactoriesInstances(Class<T> type,
Class<?>[] parameterTypes, ClassLoader classLoader, Object[] args,
Set<String> names) {
List<T> instances = new ArrayList<>(names.size());
for (String name : names) {
try {
Class<?> instanceClass = ClassUtils.forName(name, classLoader);
Assert.isAssignable(type, instanceClass);
Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);
T instance = (T) BeanUtils.instantiateClass(constructor, args);
instances.add(instance);
}
catch (Throwable ex) {
throw new IllegalArgumentException(
"Cannot instantiate " + type + " : " + name, ex);
};
}
return instances;
}
}