| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package com.alibaba.dubbo.config.spring.context.annotation; |
| |
| import com.alibaba.dubbo.config.AbstractConfig; |
| import com.alibaba.dubbo.config.spring.beans.factory.annotation.DubboConfigBindingBeanPostProcessor; |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| import org.springframework.beans.factory.config.BeanDefinition; |
| import org.springframework.beans.factory.support.AbstractBeanDefinition; |
| import org.springframework.beans.factory.support.BeanDefinitionBuilder; |
| import org.springframework.beans.factory.support.BeanDefinitionReaderUtils; |
| import org.springframework.beans.factory.support.BeanDefinitionRegistry; |
| import org.springframework.context.EnvironmentAware; |
| import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; |
| import org.springframework.core.annotation.AnnotationAttributes; |
| import org.springframework.core.env.ConfigurableEnvironment; |
| import org.springframework.core.env.Environment; |
| import org.springframework.core.type.AnnotationMetadata; |
| import org.springframework.util.Assert; |
| import org.springframework.util.CollectionUtils; |
| import org.springframework.util.StringUtils; |
| |
| import java.util.Collections; |
| import java.util.LinkedHashSet; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import static com.alibaba.dubbo.config.spring.util.PropertySourcesUtils.getSubProperties; |
| import static com.alibaba.dubbo.config.spring.util.PropertySourcesUtils.normalizePrefix; |
| import static org.springframework.beans.factory.support.BeanDefinitionBuilder.rootBeanDefinition; |
| import static org.springframework.beans.factory.support.BeanDefinitionReaderUtils.registerWithGeneratedName; |
| |
| /** |
| * {@link AbstractConfig Dubbo Config} binding Bean registrar |
| * |
| * @see EnableDubboConfigBinding |
| * @see DubboConfigBindingBeanPostProcessor |
| * @since 2.5.8 |
| */ |
| public class DubboConfigBindingRegistrar implements ImportBeanDefinitionRegistrar, EnvironmentAware { |
| |
| private final Log log = LogFactory.getLog(getClass()); |
| |
| private ConfigurableEnvironment environment; |
| |
| @Override |
| public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { |
| |
| AnnotationAttributes attributes = AnnotationAttributes.fromMap( |
| importingClassMetadata.getAnnotationAttributes(EnableDubboConfigBinding.class.getName())); |
| |
| registerBeanDefinitions(attributes, registry); |
| |
| } |
| |
| protected void registerBeanDefinitions(AnnotationAttributes attributes, BeanDefinitionRegistry registry) { |
| |
| String prefix = environment.resolvePlaceholders(attributes.getString("prefix")); |
| |
| Class<? extends AbstractConfig> configClass = attributes.getClass("type"); |
| |
| boolean multiple = attributes.getBoolean("multiple"); |
| |
| registerDubboConfigBeans(prefix, configClass, multiple, registry); |
| |
| } |
| |
| private void registerDubboConfigBeans(String prefix, |
| Class<? extends AbstractConfig> configClass, |
| boolean multiple, |
| BeanDefinitionRegistry registry) { |
| |
| Map<String, String> properties = getSubProperties(environment.getPropertySources(), prefix); |
| |
| if (CollectionUtils.isEmpty(properties)) { |
| if (log.isDebugEnabled()) { |
| log.debug("There is no property for binding to dubbo config class [" + configClass.getName() |
| + "] within prefix [" + prefix + "]"); |
| } |
| return; |
| } |
| |
| Set<String> beanNames = multiple ? resolveMultipleBeanNames(properties) : |
| Collections.singleton(resolveSingleBeanName(properties, configClass, registry)); |
| |
| for (String beanName : beanNames) { |
| |
| registerDubboConfigBean(beanName, configClass, registry); |
| |
| registerDubboConfigBindingBeanPostProcessor(prefix, beanName, multiple, registry); |
| |
| } |
| |
| } |
| |
| private void registerDubboConfigBean(String beanName, Class<? extends AbstractConfig> configClass, |
| BeanDefinitionRegistry registry) { |
| |
| BeanDefinitionBuilder builder = rootBeanDefinition(configClass); |
| |
| AbstractBeanDefinition beanDefinition = builder.getBeanDefinition(); |
| |
| registry.registerBeanDefinition(beanName, beanDefinition); |
| |
| if (log.isInfoEnabled()) { |
| log.info("The dubbo config bean definition [name : " + beanName + ", class : " + configClass.getName() + |
| "] has been registered."); |
| } |
| |
| } |
| |
| private void registerDubboConfigBindingBeanPostProcessor(String prefix, String beanName, boolean multiple, |
| BeanDefinitionRegistry registry) { |
| |
| Class<?> processorClass = DubboConfigBindingBeanPostProcessor.class; |
| |
| BeanDefinitionBuilder builder = rootBeanDefinition(processorClass); |
| |
| String actualPrefix = multiple ? normalizePrefix(prefix) + beanName : prefix; |
| |
| builder.addConstructorArgValue(actualPrefix).addConstructorArgValue(beanName); |
| |
| AbstractBeanDefinition beanDefinition = builder.getBeanDefinition(); |
| |
| beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); |
| |
| registerWithGeneratedName(beanDefinition, registry); |
| |
| if (log.isInfoEnabled()) { |
| log.info("The BeanPostProcessor bean definition [" + processorClass.getName() |
| + "] for dubbo config bean [name : " + beanName + "] has been registered."); |
| } |
| |
| } |
| |
| @Override |
| public void setEnvironment(Environment environment) { |
| |
| Assert.isInstanceOf(ConfigurableEnvironment.class, environment); |
| |
| this.environment = (ConfigurableEnvironment) environment; |
| |
| } |
| |
| private Set<String> resolveMultipleBeanNames(Map<String, String> properties) { |
| |
| Set<String> beanNames = new LinkedHashSet<String>(); |
| |
| for (String propertyName : properties.keySet()) { |
| |
| int index = propertyName.indexOf("."); |
| |
| if (index > 0) { |
| |
| String beanName = propertyName.substring(0, index); |
| |
| beanNames.add(beanName); |
| } |
| |
| } |
| |
| return beanNames; |
| |
| } |
| |
| private String resolveSingleBeanName(Map<String, String> properties, Class<? extends AbstractConfig> configClass, |
| BeanDefinitionRegistry registry) { |
| |
| String beanName = properties.get("id"); |
| |
| if (!StringUtils.hasText(beanName)) { |
| BeanDefinitionBuilder builder = rootBeanDefinition(configClass); |
| beanName = BeanDefinitionReaderUtils.generateBeanName(builder.getRawBeanDefinition(), registry); |
| } |
| |
| return beanName; |
| |
| } |
| |
| } |