Java tutorial
/* * 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.MutablePropertyValues; import org.springframework.beans.PropertyValues; 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.*; import org.springframework.core.type.AnnotationMetadata; import org.springframework.util.Assert; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; import java.util.*; import static com.alibaba.dubbo.config.spring.util.PropertySourcesUtils.getSubProperties; 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) { PropertySources propertySources = environment.getPropertySources(); Map<String, String> properties = getSubProperties(propertySources, 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(prefix, properties) : Collections.singleton(resolveSingleBeanName(configClass, properties, registry)); for (String beanName : beanNames) { registerDubboConfigBean(beanName, configClass, registry); MutablePropertyValues propertyValues = resolveBeanPropertyValues(beanName, multiple, properties); registerDubboConfigBindingBeanPostProcessor(beanName, propertyValues, 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 beanName, PropertyValues propertyValues, BeanDefinitionRegistry registry) { Class<?> processorClass = DubboConfigBindingBeanPostProcessor.class; BeanDefinitionBuilder builder = rootBeanDefinition(processorClass); builder.addConstructorArgValue(beanName).addConstructorArgValue(propertyValues); 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."); } } private MutablePropertyValues resolveBeanPropertyValues(String beanName, boolean multiple, Map<String, String> properties) { MutablePropertyValues propertyValues = new MutablePropertyValues(); if (multiple) { // For Multiple Beans MutablePropertySources propertySources = new MutablePropertySources(); propertySources.addFirst(new MapPropertySource(beanName, new TreeMap<String, Object>(properties))); Map<String, String> subProperties = getSubProperties(propertySources, beanName); propertyValues.addPropertyValues(subProperties); } else { // For Single Bean for (Map.Entry<String, String> entry : properties.entrySet()) { String propertyName = entry.getKey(); if (!propertyName.contains(".")) { // ignore property name with "." propertyValues.addPropertyValue(propertyName, entry.getValue()); } } } return propertyValues; } @Override public void setEnvironment(Environment environment) { Assert.isInstanceOf(ConfigurableEnvironment.class, environment); this.environment = (ConfigurableEnvironment) environment; } private Set<String> resolveMultipleBeanNames(String prefix, 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(Class<? extends AbstractConfig> configClass, Map<String, String> properties, BeanDefinitionRegistry registry) { String beanName = properties.get("id"); if (!StringUtils.hasText(beanName)) { BeanDefinitionBuilder builder = rootBeanDefinition(configClass); beanName = BeanDefinitionReaderUtils.generateBeanName(builder.getRawBeanDefinition(), registry); } return beanName; } }