JDK 的工具 java.util.Observer 是一个订阅者 java.util.Observable 是一个发布者 发布者 : 订阅者 = N :N 示例代码 public class ObserveDemo extends Observable{ public static void main(String[] args) { ObserveDemo observable = new ObserveTest(); Observer observer = (obs,event) ->{ System.out.println(event); }; observable.addObserver(observer); observable.setChanged(); observable.notifyObservers("aaa"); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 1 2 3 4 5 6 7 8 9 10 11 12 13 事件/监听模式 java.util.EventListener 事件监听者 java.util.EventObject 事件对象 事件对象总是关联着事件源() Spring 事件监听 ApplicationEvent Spring事件 ApplicationListener Spring事件监听器 样例代码如下 public class SpringEventListenerDemo { public static void main(String[] args) { //注解驱动的Spring上下文 AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); //监听器 ApplicationListener listener = event -> System.out.println(event.getSource()); //定义事件 ApplicationEvent event = new ApplicationEvent("Hello World"){}; //注册监听器 context.addApplicationListener(listener); //刷新容器 context.refresh(); //发布事件 context.publishEvent(event); } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 *Spring Boot 相关事件* ApplicationEnvironmentPreparedEvent ApplicationPreparedEvent ApplicationStartingEvent ApplicationReadyEvent ApplicationFailedEvent #### Spring Boot监听器 ConfigFileApplicationListener 管理配置文件例如 application.yml,application.properties application-{profile}.properties profile = dev , test 优先级 application-{profile}.properties application.properties 默认配置文件位置 public class ConfigFileApplicationListener implements EnvironmentPostProcessor, SmartApplicationListener, Ordered { ... //默认配置文件地址 类路径 、类路径/config 、当前文件路径、 当前文件路径/config private static final String DEFAULT_SEARCH_LOCATIONS = "classpath:/,classpath:/config/,file:./,file:./config/"; ... } 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 默认优先级 /** * The default order for the processor. */ //最高优先级+10 public static final int DEFAULT_ORDER = Ordered.HIGHEST_PRECEDENCE + 10; 1 2 3 4 5 1 2 3 4 5 SPI Java SPI : java.util.ServiceLoader Spring SPI 如何控制顺序 (数值越小越优先) 实现Ordered接口 int getOrder(); 方法 使用@Order注解 代码解释如下 public interface Ordered { /** * Useful constant for the highest precedence value. * @see java.lang.Integer#MIN_VALUE */ //z最高优先级 int HIGHEST_PRECEDENCE = Integer.MIN_VALUE; /** * Useful constant for the lowest precedence value. * @see java.lang.Integer#MAX_VALUE */ //最低优先级 int LOWEST_PRECEDENCE = Integer.MAX_VALUE; /** * Get the order value of this object. *

Higher values are interpreted as lower priority. As a consequence, * the object with the lowest value has the highest priority (somewhat * analogous to Servlet {@code load-on-startup} values). *

Same order values will result in arbitrary sort positions for the * affected objects. * @return the order value * @see #HIGHEST_PRECEDENCE * @see #LOWEST_PRECEDENCE */ int getOrder(); } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 1 Spring CLoud 事件/监听器 BootstrapApplicationListener 负责加载bootstrap.yml,bootstrap.properties 负责初始化bootstrap-context BootstrapApplicationListener#bootstrapServiceContext final ConfigurableApplicationContext context = builder.run(); //context (id) -> bootstrap 1 2 1 2 加载的优先级高于 ConfigFileApplicationListener,因此 application.yml即使定义也配置不到(先加载 bootstrap.yml,后加载 application.yml) 优先级 : 最高优先级 + 5 public static final int DEFAULT_ORDER = Ordered.HIGHEST_PRECEDENCE + 5; 类比ClassLoader AppClassLoader BootstrapClassloader 1 2 1 2 Env 端点:EnvironmentEndpoint Environment关联着多个带名称的PropertySource 参考 Spring 源码 AbstractRefreshableWebApplicationContext protected void initPropertySources() { ConfigurableEnvironment env = getEnvironment(); if (env instanceof ConfigurableWebEnvironment) { ((ConfigurableWebEnvironment) env).initPropertySources(this.servletContext, this.servletConfig); } } 1 2 3 4 5 6 7 1 2 3 4 5 6 7 Environment 有两种实现方式 普通版本 StandardEnvironment Web 版本 StandardServletEnvironment ####Environment 层次关系 Environment AbstractEnvironment StandardEnvironment (普通版本) StandardServletEnvironment (Web 版本) Env 端点内容展示介绍 Java System#getProperties 实现 :名称为 systemProperties,对应内容 System#getProperties() Java System#env 实现(环境变量):名称为 systemEnvironment,对应内容 System#getenv() 实现自定义配置 实现 PropertySourceLocator 接口 作为配置 (加上 @Configuration ) 新建一个 Spring SPI META-INF/spring.factories 检索文件 建在 resources 目录下 官方文档介绍 2.6 Customizing the Bootstrap Property Sources 实现 PropertySourceLocator 接口 @Configuration @Order(Ordered.HIGHEST_PRECEDENCE) public class MyPropertySourcesLocator implements PropertySourceLocator { /** * @param environment the current Environment * @return a PropertySource or null if there is none * @throws IllegalStateException if there is a fail fast condition */ @Override public PropertySource locate(Environment environment) { Map map = new HashMap<>(); map.put("server.port","9090"); MapPropertySource myConfig = new MapPropertySource("MyProperties", map); return myConfig; } } 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 配置 Spring SPI META-INF/spring.factories org.springframework.cloud.bootstrap.BootstrapConfiguration=\ com.example.demo.xmg.six_client.MyPropertySourcesLocator 1 2 3 注意事项 Environment 允许出现同名的配置,当出现同名配置时优先级高的胜出 内部实现 MutablePropertySources private final List> propertySourceList = new CopyOnWriteArrayList>(); 1 2 1 2 propertySourceList 有顺序,可以通过 MutablePropertySources#addFirst 提高优先级,相当于调用 list#set(0,obj) MutablePropertySources#addFirst 实现方式 public void addFirst(PropertySource propertySource) { if (logger.isDebugEnabled()) { logger.debug("Adding PropertySource '" + propertySource.getName() + "' with highest search precedence"); } //删除已经有的数据 removeIfPresent(propertySource); //把数据放到第一位 this.propertySourceList.add(0, propertySource); } // 删除如果存在 就是直接删除list中的数据 protected void removeIfPresent(PropertySource propertySource) { this.propertySourceList.remove(propertySource); }

查看原文 >>
相关文章