|
| 1 | +package io.kimmking.javacourse.demo; |
| 2 | + |
| 3 | +import org.springframework.beans.MutablePropertyValues; |
| 4 | +import org.springframework.beans.factory.support.*; |
| 5 | +import org.springframework.context.EnvironmentAware; |
| 6 | +import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; |
| 7 | +import org.springframework.core.annotation.AnnotationAttributes; |
| 8 | +import org.springframework.core.env.ConfigurableEnvironment; |
| 9 | +import org.springframework.core.env.Environment; |
| 10 | +import org.springframework.core.type.AnnotationMetadata; |
| 11 | +import org.springframework.util.CollectionUtils; |
| 12 | +import org.springframework.util.StringUtils; |
| 13 | + |
| 14 | +import java.util.*; |
| 15 | + |
| 16 | +import static io.kimmking.javacourse.demo.PropertySourcesUtils.getSubProperties; |
| 17 | +import static org.springframework.beans.factory.support.BeanDefinitionBuilder.rootBeanDefinition; |
| 18 | + |
| 19 | +/** |
| 20 | + * This class is cloned and modified from https://github.com/apache/dubbo/blob/58d1259cb9d89528594e43db5d8667179005dcfc/dubbo-config/dubbo-config-spring/src/main/java/com/alibaba/dubbo/config/spring/context/annotation/DubboConfigBindingsRegistrar.java. |
| 21 | + * |
| 22 | + * @Author : kimmking(kimmking@apache.org) |
| 23 | + * @create 2022/11/29 16:09 |
| 24 | + */ |
| 25 | +public class DemoConfigBindingsRegistrar implements ImportBeanDefinitionRegistrar, EnvironmentAware { |
| 26 | + |
| 27 | + private ConfigurableEnvironment environment; |
| 28 | + |
| 29 | + @Override |
| 30 | + public void setEnvironment(Environment _environment) { |
| 31 | + this.environment = (ConfigurableEnvironment) _environment; |
| 32 | + } |
| 33 | + |
| 34 | + @Override |
| 35 | + public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry, BeanNameGenerator importBeanNameGenerator) { |
| 36 | + registerBeanDefinitions(importingClassMetadata, registry); |
| 37 | + } |
| 38 | + |
| 39 | + @Override |
| 40 | + public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { |
| 41 | + |
| 42 | + AnnotationAttributes attributes = AnnotationAttributes.fromMap( |
| 43 | + importingClassMetadata.getAnnotationAttributes(EnableDemoConfigBindings.class.getName())); |
| 44 | + String prefix = environment.resolvePlaceholders(attributes.getString("prefix")); |
| 45 | + Class<? extends DemoConfig> configClass = attributes.getClass("type"); |
| 46 | + boolean multiple = attributes.getBoolean("multiple"); |
| 47 | + registerDubboConfigBeans(prefix, configClass, multiple, registry); |
| 48 | + } |
| 49 | + |
| 50 | + private void registerDubboConfigBeans(String prefix, |
| 51 | + Class<? extends DemoConfig> configClass, |
| 52 | + boolean multiple, |
| 53 | + BeanDefinitionRegistry registry) { |
| 54 | + Map<String, Object> properties = getSubProperties(environment.getPropertySources(), prefix); |
| 55 | + if (CollectionUtils.isEmpty(properties)) { |
| 56 | + System.out.println("There is no property for binding to demo config class [" + configClass.getName() |
| 57 | + + "] within prefix [" + prefix + "]"); |
| 58 | + return; |
| 59 | + } |
| 60 | + Set<String> beanNames = multiple ? resolveMultipleBeanNames(properties) : |
| 61 | + Collections.singleton(resolveSingleBeanName(properties, configClass, registry)); |
| 62 | + Map<String, Map<String, Object>> groupProperties = getGroupProperties(properties, beanNames); |
| 63 | + for (String beanName : beanNames) { |
| 64 | + registerDemoConfigBean(beanName, configClass, registry, groupProperties.get(beanName)); |
| 65 | + //registerDubboConfigBindingBeanPostProcessor(prefix, beanName, multiple, registry); |
| 66 | + } |
| 67 | + //registerDubboConfigBeanCustomizers(registry); |
| 68 | + } |
| 69 | + |
| 70 | + private Map<String, Map<String, Object>> getGroupProperties(Map<String, Object> properties, Set<String> beanNames) { |
| 71 | + Map<String, Map<String, Object>> map = new HashMap<>(); |
| 72 | + for (String propertyName : properties.keySet()) { |
| 73 | + int index = propertyName.indexOf("."); |
| 74 | + if (index > 0) { |
| 75 | + String beanName = propertyName.substring(0, index); |
| 76 | + String beanPropertyName = propertyName.substring(index + 1); |
| 77 | + if (beanNames.contains(beanName)) { |
| 78 | + Map<String, Object> group = map.get(beanName); |
| 79 | + if (group == null) { |
| 80 | + group = new HashMap<>(); |
| 81 | + map.put(beanName, group); |
| 82 | + } |
| 83 | + group.put(beanPropertyName, properties.get(propertyName)); |
| 84 | + } |
| 85 | + } |
| 86 | + } |
| 87 | + return map; |
| 88 | + } |
| 89 | + |
| 90 | + private void registerDemoConfigBean(String beanName, Class<? extends DemoConfig> configClass, |
| 91 | + BeanDefinitionRegistry registry, Map<String, Object> properties) { |
| 92 | + BeanDefinitionBuilder builder = rootBeanDefinition(configClass); |
| 93 | + AbstractBeanDefinition beanDefinition = builder.getBeanDefinition(); |
| 94 | + // Convert Map to MutablePropertyValues |
| 95 | + MutablePropertyValues propertyValues = new MutablePropertyValues(properties); |
| 96 | + beanDefinition.setPropertyValues(propertyValues); |
| 97 | + registry.registerBeanDefinition(beanName, beanDefinition); |
| 98 | + System.out.println("The demo config bean definition [name : " + beanName + ", class : " + configClass.getName() + |
| 99 | + "] has been registered."); |
| 100 | + } |
| 101 | + |
| 102 | + private Set<String> resolveMultipleBeanNames(Map<String, Object> properties) { |
| 103 | + Set<String> beanNames = new LinkedHashSet<String>(); |
| 104 | + for (String propertyName : properties.keySet()) { |
| 105 | + int index = propertyName.indexOf("."); |
| 106 | + if (index > 0) { |
| 107 | + String beanName = propertyName.substring(0, index); |
| 108 | + beanNames.add(beanName); |
| 109 | + } |
| 110 | + } |
| 111 | + return beanNames; |
| 112 | + } |
| 113 | + |
| 114 | + private String resolveSingleBeanName(Map<String, Object> properties, Class<? extends DemoConfig> configClass, |
| 115 | + BeanDefinitionRegistry registry) { |
| 116 | + String beanName = (String) properties.get("demoName"); |
| 117 | + if (!StringUtils.hasText(beanName)) { |
| 118 | + BeanDefinitionBuilder builder = rootBeanDefinition(configClass); |
| 119 | + beanName = BeanDefinitionReaderUtils.generateBeanName(builder.getRawBeanDefinition(), registry); |
| 120 | + } |
| 121 | + return beanName; |
| 122 | + } |
| 123 | + |
| 124 | +} |
0 commit comments