本文主要研究一下DubboDefaultPropertiesEnvironmentPostProcessor
dubbo-spring-boot-project-2.7.3/dubbo-spring-boot-compatible/autoconfigure/src/main/java/org/apache/dubbo/spring/boot/env/DubboDefaultPropertiesEnvironmentPostProcessor.java
public class DubboDefaultPropertiesEnvironmentPostProcessor implements EnvironmentPostProcessor, Ordered { /** * The name of default {@link PropertySource} defined in SpringApplication#configurePropertySources method. */ public static final String PROPERTY_SOURCE_NAME = "defaultProperties"; /** * The property name of "spring.main.allow-bean-definition-overriding". * Please refer to: https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.1-Release-Notes#bean-overriding */ public static final String ALLOW_BEAN_DEFINITION_OVERRIDING_PROPERTY = "spring.main.allow-bean-definition-overriding"; @Override public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { MutablePropertySources propertySources = environment.getPropertySources(); Map<String, Object> defaultProperties = createDefaultProperties(environment); if (!CollectionUtils.isEmpty(defaultProperties)) { addOrReplace(propertySources, defaultProperties); } } @Override public int getOrder() { return LOWEST_PRECEDENCE; } private Map<String, Object> createDefaultProperties(ConfigurableEnvironment environment) { Map<String, Object> defaultProperties = new HashMap<String, Object>(); setDubboApplicationNameProperty(environment, defaultProperties); setDubboConfigMultipleProperty(defaultProperties); setDubboApplicationQosEnableProperty(defaultProperties); setAllowBeanDefinitionOverriding(defaultProperties); return defaultProperties; } private void setDubboApplicationNameProperty(Environment environment, Map<String, Object> defaultProperties) { String springApplicationName = environment.getProperty(SPRING_APPLICATION_NAME_PROPERTY); if (StringUtils.hasLength(springApplicationName) && !environment.containsProperty(DUBBO_APPLICATION_NAME_PROPERTY)) { defaultProperties.put(DUBBO_APPLICATION_NAME_PROPERTY, springApplicationName); } } private void setDubboConfigMultipleProperty(Map<String, Object> defaultProperties) { defaultProperties.put(DUBBO_CONFIG_MULTIPLE_PROPERTY, Boolean.TRUE.toString()); } private void setDubboApplicationQosEnableProperty(Map<String, Object> defaultProperties) { defaultProperties.put(DUBBO_APPLICATION_QOS_ENABLE_PROPERTY, Boolean.FALSE.toString()); } /** * Set {@link #ALLOW_BEAN_DEFINITION_OVERRIDING_PROPERTY "spring.main.allow-bean-definition-overriding"} to be * <code>true</code> as default. * * @param defaultProperties the default {@link Properties properties} * @see #ALLOW_BEAN_DEFINITION_OVERRIDING_PROPERTY * @since 2.7.1 */ private void setAllowBeanDefinitionOverriding(Map<String, Object> defaultProperties) { defaultProperties.put(ALLOW_BEAN_DEFINITION_OVERRIDING_PROPERTY, Boolean.TRUE.toString()); } /** * Copy from BusEnvironmentPostProcessor#addOrReplace(MutablePropertySources, Map) * * @param propertySources {@link MutablePropertySources} * @param map Default Dubbo Properties */ private void addOrReplace(MutablePropertySources propertySources, Map<String, Object> map) { MapPropertySource target = null; if (propertySources.contains(PROPERTY_SOURCE_NAME)) { PropertySource<?> source = propertySources.get(PROPERTY_SOURCE_NAME); if (source instanceof MapPropertySource) { target = (MapPropertySource) source; for (String key : map.keySet()) { if (!target.containsProperty(key)) { target.getSource().put(key, map.get(key)); } } } } if (target == null) { target = new MapPropertySource(PROPERTY_SOURCE_NAME, map); } if (!propertySources.contains(PROPERTY_SOURCE_NAME)) { propertySources.addLast(target); } } }
这里默认设置了DUBBO_APPLICATION_NAME_PROPERTY为springApplicationName、DUBBO_CONFIG_MULTIPLE_PROPERTY为true、DUBBO_APPLICATION_QOS_ENABLE_PROPERTY为false
),最后通过addOrReplace方法把defaultProperties覆盖到propertySources;getOrder方法返回的是LOWEST_PRECEDENCE dubbo-spring-boot-project-2.7.3/dubbo-spring-boot-autoconfigure/src/test/java/org/apache/dubbo/spring/boot/env/DubboDefaultPropertiesEnvironmentPostProcessorTest.java
public class DubboDefaultPropertiesEnvironmentPostProcessorTest { private DubboDefaultPropertiesEnvironmentPostProcessor instance = new DubboDefaultPropertiesEnvironmentPostProcessor(); private SpringApplication springApplication = new SpringApplication(); @Test public void testOrder() { Assert.assertEquals(Ordered.LOWEST_PRECEDENCE, instance.getOrder()); } @Test public void testPostProcessEnvironment() { MockEnvironment environment = new MockEnvironment(); // Case 1 : Not Any property instance.postProcessEnvironment(environment, springApplication); // Get PropertySources MutablePropertySources propertySources = environment.getPropertySources(); // Nothing to change PropertySource defaultPropertySource = propertySources.get("defaultProperties"); Assert.assertNotNull(defaultPropertySource); Assert.assertEquals("true", defaultPropertySource.getProperty("dubbo.config.multiple")); Assert.assertEquals("false", defaultPropertySource.getProperty("dubbo.application.qos-enable")); // Case 2 : Only set property "spring.application.name" environment.setProperty("spring.application.name", "demo-dubbo-application"); instance.postProcessEnvironment(environment, springApplication); defaultPropertySource = propertySources.get("defaultProperties"); Object dubboApplicationName = defaultPropertySource.getProperty("dubbo.application.name"); Assert.assertEquals("demo-dubbo-application", dubboApplicationName); // Case 3 : Only set property "dubbo.application.name" // Rest environment environment = new MockEnvironment(); propertySources = environment.getPropertySources(); environment.setProperty("dubbo.application.name", "demo-dubbo-application"); instance.postProcessEnvironment(environment, springApplication); defaultPropertySource = propertySources.get("defaultProperties"); Assert.assertNotNull(defaultPropertySource); dubboApplicationName = environment.getProperty("dubbo.application.name"); Assert.assertEquals("demo-dubbo-application", dubboApplicationName); // Case 4 : If "defaultProperties" PropertySource is present in PropertySources // Rest environment environment = new MockEnvironment(); propertySources = environment.getPropertySources(); propertySources.addLast(new MapPropertySource("defaultProperties", new HashMap<String, Object>())); environment.setProperty("spring.application.name", "demo-dubbo-application"); instance.postProcessEnvironment(environment, springApplication); defaultPropertySource = propertySources.get("defaultProperties"); dubboApplicationName = defaultPropertySource.getProperty("dubbo.application.name"); Assert.assertEquals("demo-dubbo-application", dubboApplicationName); // Case 5 : Rest dubbo.config.multiple and dubbo.application.qos-enable environment = new MockEnvironment(); propertySources = environment.getPropertySources(); propertySources.addLast(new MapPropertySource("defaultProperties", new HashMap<String, Object>())); environment.setProperty("dubbo.config.multiple", "false"); environment.setProperty("dubbo.application.qos-enable", "true"); instance.postProcessEnvironment(environment, springApplication); Assert.assertEquals("false", environment.getProperty("dubbo.config.multiple")); Assert.assertEquals("true", environment.getProperty("dubbo.application.qos-enable")); } }
DubboDefaultPropertiesEnvironmentPostProcessor实现了EnvironmentPostProcessor, Ordered接口;postProcessEnvironment方法首先从environment获取MutablePropertySources,然后通过createDefaultProperties创建默认配置defaultProperties( 这里默认设置了DUBBO_APPLICATION_NAME_PROPERTY为springApplicationName、DUBBO_CONFIG_MULTIPLE_PROPERTY为true、DUBBO_APPLICATION_QOS_ENABLE_PROPERTY为false
),最后通过addOrReplace方法把defaultProperties覆盖到propertySources;getOrder方法返回的是LOWEST_PRECEDENCE