想要了解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; } }