想要了解springboot加载配置文件,要了解观察者模式,以及相应的实现方式java
一、观察者模式(Publish/Subscribe):spring
举例说明:设计模式
报社方负责出版报纸.springboot
你订阅了该报社的报纸,那么只要报社发布了新报纸,就会通知你,或发到你手上.app
若是你不想再读报纸,能够取消订阅,这样,报社发布了新报纸就不会再通知你.url
jdk不只提供了Observable类、Observer接口支持观察者模式,并且也提供了EventObject类、EventListener接口来支持事件监听模式,spa
虽然二者属于同一类型模式,都属于回调机制,主动推送消息,但使用场景有些区别。.net
1. 事件-监听机制设计
2. 观察者模式
观察者(Observer)至关于事件监听者(监听器),被观察者(Observable)至关于事件源和事件,执行逻辑时通知observer便可触发oberver的update,3d
同时 可传被观察者和参数。简化了事件-监听模式的实现
链接为设计模式
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; } }