提交 d5284338 编写于 作者: M Mercy 提交者: ken.lj

Merge pull request #1016, Annotation Enhancemane

* Add compatibility for Spring 3.2.x to resolve
* Add final to BEAN_NAME field
* @EnableDubboConfig & @EnableDubbo
上级 1f2dcbe2
......@@ -93,6 +93,12 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
......
......@@ -20,19 +20,9 @@ import com.alibaba.dubbo.common.logger.Logger;
import com.alibaba.dubbo.common.logger.LoggerFactory;
import com.alibaba.dubbo.common.utils.ConcurrentHashSet;
import com.alibaba.dubbo.common.utils.ReflectUtils;
import com.alibaba.dubbo.config.AbstractConfig;
import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ConsumerConfig;
import com.alibaba.dubbo.config.ModuleConfig;
import com.alibaba.dubbo.config.MonitorConfig;
import com.alibaba.dubbo.config.ProtocolConfig;
import com.alibaba.dubbo.config.ProviderConfig;
import com.alibaba.dubbo.config.ReferenceConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.ServiceConfig;
import com.alibaba.dubbo.config.*;
import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
......
......@@ -15,16 +15,10 @@
*/
package com.alibaba.dubbo.config.spring;
import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ConsumerConfig;
import com.alibaba.dubbo.config.ModuleConfig;
import com.alibaba.dubbo.config.MonitorConfig;
import com.alibaba.dubbo.config.ReferenceConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.*;
import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory;
import com.alibaba.dubbo.config.support.Parameter;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
......
......@@ -15,16 +15,9 @@
*/
package com.alibaba.dubbo.config.spring;
import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ModuleConfig;
import com.alibaba.dubbo.config.MonitorConfig;
import com.alibaba.dubbo.config.ProtocolConfig;
import com.alibaba.dubbo.config.ProviderConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.ServiceConfig;
import com.alibaba.dubbo.config.*;
import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.dubbo.config.spring.extension.SpringExtensionFactory;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
......
package com.alibaba.dubbo.config.spring.beans.factory.annotation;
import com.alibaba.dubbo.common.utils.Assert;
import com.alibaba.dubbo.config.spring.context.annotation.DubboConfigBindingRegistrar;
import com.alibaba.dubbo.config.spring.context.annotation.EnableDubboConfigBinding;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.PropertyValues;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.validation.DataBinder;
import java.util.Arrays;
/**
* Dubbo Config Binding {@link BeanPostProcessor}
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
* @see EnableDubboConfigBinding
* @see DubboConfigBindingRegistrar
* @since 2.5.8
*/
public class DubboConfigBindingBeanPostProcessor implements BeanPostProcessor {
private final Log log = LogFactory.getLog(getClass());
/**
* Binding Bean Name
*/
private final String beanName;
/**
* Binding {@link PropertyValues}
*/
private final PropertyValues propertyValues;
/**
* @param beanName Binding Bean Name
* @param propertyValues {@link PropertyValues}
*/
public DubboConfigBindingBeanPostProcessor(String beanName, PropertyValues propertyValues) {
Assert.notNull(beanName, "The name of bean must not be null");
Assert.notNull(propertyValues, "The PropertyValues of bean must not be null");
this.beanName = beanName;
this.propertyValues = propertyValues;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (beanName.equals(this.beanName)) {
DataBinder dataBinder = new DataBinder(bean);
// TODO ignore invalid fields by annotation attribute
dataBinder.setIgnoreInvalidFields(true);
dataBinder.bind(propertyValues);
if (log.isInfoEnabled()) {
log.info("The properties of bean [name : " + beanName + "] have been binding by values : "
+ Arrays.asList(propertyValues.getPropertyValues()));
}
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
package com.alibaba.dubbo.config.spring.beans.factory.annotation;
import com.alibaba.dubbo.common.logger.Logger;
import com.alibaba.dubbo.common.logger.LoggerFactory;
import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.dubbo.config.spring.ServiceBean;
import com.alibaba.dubbo.config.spring.context.annotation.DubboClassPathBeanDefinitionScanner;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.config.*;
import org.springframework.beans.factory.support.*;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.*;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.util.*;
import java.util.*;
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.rootBeanDefinition;
import static org.springframework.beans.factory.support.BeanDefinitionReaderUtils.registerWithGeneratedName;
import static org.springframework.context.annotation.AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR;
import static org.springframework.core.annotation.AnnotationUtils.findAnnotation;
import static org.springframework.util.ClassUtils.resolveClassName;
/**
* {@link Service} Annotation
* {@link BeanDefinitionRegistryPostProcessor Bean Definition Registry Post Processor}
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
* @since 2.5.8
*/
public class ServiceAnnotationBeanPostProcessor implements BeanDefinitionRegistryPostProcessor, EnvironmentAware,
ResourceLoaderAware, BeanClassLoaderAware {
private final Logger logger = LoggerFactory.getLogger(getClass());
private final Set<String> packagesToScan;
private Environment environment;
private ResourceLoader resourceLoader;
private ClassLoader classLoader;
public ServiceAnnotationBeanPostProcessor(String... packagesToScan) {
this(Arrays.asList(packagesToScan));
}
public ServiceAnnotationBeanPostProcessor(Collection<String> packagesToScan) {
this(new LinkedHashSet<String>(packagesToScan));
}
public ServiceAnnotationBeanPostProcessor(Set<String> packagesToScan) {
this.packagesToScan = packagesToScan;
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
Set<String> resolvedPackagesToScan = resolvePackagesToScan(packagesToScan);
registerServiceBeans(resolvedPackagesToScan, registry);
}
/**
* Registers Beans whose classes was annotated {@link Service}
*
* @param packagesToScan The base packages to scan
* @param registry {@link BeanDefinitionRegistry}
*/
private void registerServiceBeans(Set<String> packagesToScan, BeanDefinitionRegistry registry) {
DubboClassPathBeanDefinitionScanner scanner =
new DubboClassPathBeanDefinitionScanner(registry, environment, resourceLoader);
BeanNameGenerator beanNameGenerator = resolveBeanNameGenerator(registry);
scanner.setBeanNameGenerator(beanNameGenerator);
scanner.addIncludeFilter(new AnnotationTypeFilter(Service.class));
for (String packageToScan : packagesToScan) {
Set<BeanDefinitionHolder> beanDefinitionHolders = scanner.doScan(packageToScan);
if (CollectionUtils.isEmpty(beanDefinitionHolders)) {
if (logger.isInfoEnabled()) {
logger.info("No Spring Bean annotating Dubbo's @Service was found in Spring BeanFactory , " +
"it maybe that some bean was also annotated @Component .");
logger.info("It will try to find all Bean types annotating Dubbo's @Service from all Bean Definitions");
}
beanDefinitionHolders = findServiceBeanDefinitionHolders(scanner, packageToScan, registry, beanNameGenerator);
}
if (!CollectionUtils.isEmpty(beanDefinitionHolders)) {
for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) {
registerServiceBean(beanDefinitionHolder, registry);
}
if (logger.isInfoEnabled()) {
logger.info(beanDefinitionHolders.size() + " annotated Dubbo's @Service Components { " +
beanDefinitionHolders +
" } were scanned under package[" + packageToScan + "]");
}
} else {
if (logger.isWarnEnabled()) {
logger.warn("No Spring Bean annotating Dubbo's @Service was found in Spring BeanFactory");
}
}
}
}
/**
* It'd better to use BeanNameGenerator instance that should reference
* {@link ConfigurationClassPostProcessor#componentScanBeanNameGenerator},
* thus it maybe a potential problem on bean name generation.
*
* @param registry {@link BeanDefinitionRegistry}
* @return {@link BeanNameGenerator} instance
* @see SingletonBeanRegistry
* @see AnnotationConfigUtils#CONFIGURATION_BEAN_NAME_GENERATOR
* @see ConfigurationClassPostProcessor#processConfigBeanDefinitions
* @since 2.5.8
*/
private BeanNameGenerator resolveBeanNameGenerator(BeanDefinitionRegistry registry) {
BeanNameGenerator beanNameGenerator = null;
if (registry instanceof SingletonBeanRegistry) {
SingletonBeanRegistry singletonBeanRegistry = SingletonBeanRegistry.class.cast(registry);
beanNameGenerator = (BeanNameGenerator) singletonBeanRegistry.getSingleton(CONFIGURATION_BEAN_NAME_GENERATOR);
}
if (beanNameGenerator == null) {
if (logger.isInfoEnabled()) {
logger.info("BeanNameGenerator bean can't be found in BeanFactory with name ["
+ CONFIGURATION_BEAN_NAME_GENERATOR + "]");
logger.info("BeanNameGenerator will be a instance of " +
AnnotationBeanNameGenerator.class.getName() +
" , it maybe a potential problem on bean name generation.");
}
beanNameGenerator = new AnnotationBeanNameGenerator();
}
return beanNameGenerator;
}
/**
* Finds a {@link Set} of {@link BeanDefinitionHolder BeanDefinitionHolders} whose bean type annotated
* {@link Service} Annotation.
*
* @param scanner {@link ClassPathBeanDefinitionScanner}
* @param packageToScan pachage to scan
* @param registry {@link BeanDefinitionRegistry}
* @return non-null
* @since 2.5.8
*/
private Set<BeanDefinitionHolder> findServiceBeanDefinitionHolders(
ClassPathBeanDefinitionScanner scanner, String packageToScan, BeanDefinitionRegistry registry,
BeanNameGenerator beanNameGenerator) {
Set<BeanDefinition> beanDefinitions = scanner.findCandidateComponents(packageToScan);
Set<BeanDefinitionHolder> beanDefinitionHolders = new LinkedHashSet<BeanDefinitionHolder>(beanDefinitions.size());
for (BeanDefinition beanDefinition : beanDefinitions) {
String beanName = beanNameGenerator.generateBeanName(beanDefinition, registry);
BeanDefinitionHolder beanDefinitionHolder = new BeanDefinitionHolder(beanDefinition, beanName);
beanDefinitionHolders.add(beanDefinitionHolder);
}
return beanDefinitionHolders;
}
/**
* Registers {@link ServiceBean} from new annotated {@link Service} {@link BeanDefinition}
*
* @param beanDefinitionHolder
* @param registry
* @see ServiceBean
* @see BeanDefinition
*/
private void registerServiceBean(BeanDefinitionHolder beanDefinitionHolder, BeanDefinitionRegistry registry) {
Class<?> beanClass = resolveClass(beanDefinitionHolder);
Service service = findAnnotation(beanClass, Service.class);
Class<?> interfaceClass = resolveServiceInterfaceClass(beanClass, service);
String beanName = beanDefinitionHolder.getBeanName();
AbstractBeanDefinition serviceBeanDefinition = buildServiceBeanDefinition(service, interfaceClass, beanName);
registerWithGeneratedName(serviceBeanDefinition, registry);
}
private Class<?> resolveServiceInterfaceClass(Class<?> annotatedServiceBeanClass, Service service) {
Class<?> interfaceClass = service.interfaceClass();
if (void.class.equals(interfaceClass)) {
interfaceClass = null;
String interfaceClassName = service.interfaceName();
if (StringUtils.hasText(interfaceClassName)) {
if (ClassUtils.isPresent(interfaceClassName, classLoader)) {
interfaceClass = resolveClassName(interfaceClassName, classLoader);
}
}
}
if (interfaceClass == null) {
Class<?>[] allInterfaces = annotatedServiceBeanClass.getInterfaces();
if (allInterfaces.length > 0) {
interfaceClass = allInterfaces[0];
}
}
Assert.notNull(interfaceClass,
"@Service interfaceClass() or interfaceName() or interface class must be present!");
Assert.isTrue(interfaceClass.isInterface(),
"The type that was annotated @Service is not an interface!");
return interfaceClass;
}
private Class<?> resolveClass(BeanDefinitionHolder beanDefinitionHolder) {
BeanDefinition beanDefinition = beanDefinitionHolder.getBeanDefinition();
return resolveClass(beanDefinition);
}
private Class<?> resolveClass(BeanDefinition beanDefinition) {
String beanClassName = beanDefinition.getBeanClassName();
return resolveClassName(beanClassName, classLoader);
}
private Set<String> resolvePackagesToScan(Set<String> packagesToScan) {
Set<String> resolvedPackagesToScan = new LinkedHashSet<String>(packagesToScan.size());
for (String packageToScan : packagesToScan) {
String resolvedPackageToScan = environment.resolvePlaceholders(packageToScan);
resolvedPackagesToScan.add(resolvedPackageToScan);
}
return resolvedPackagesToScan;
}
private AbstractBeanDefinition buildServiceBeanDefinition(Service service, Class<?> interfaceClass,
String annotatedServiceBeanName) {
BeanDefinitionBuilder builder = rootBeanDefinition(ServiceBean.class)
.addConstructorArgValue(service)
// References "ref" property to annotated-@Service Bean
.addPropertyReference("ref", annotatedServiceBeanName)
.addPropertyValue("interfaceClass", interfaceClass);
/**
* Add {@link com.alibaba.dubbo.config.ProviderConfig} Bean reference
*/
String providerConfigBeanName = service.provider();
if (StringUtils.hasText(providerConfigBeanName)) {
addPropertyReference(builder, "provider", providerConfigBeanName);
}
/**
* Add {@link com.alibaba.dubbo.config.MonitorConfig} Bean reference
*/
String monitorConfigBeanName = service.monitor();
if (StringUtils.hasText(monitorConfigBeanName)) {
addPropertyReference(builder, "monitor", monitorConfigBeanName);
}
/**
* Add {@link com.alibaba.dubbo.config.ApplicationConfig} Bean reference
*/
String applicationConfigBeanName = service.application();
if (StringUtils.hasText(applicationConfigBeanName)) {
addPropertyReference(builder, "application", applicationConfigBeanName);
}
/**
* Add {@link com.alibaba.dubbo.config.ModuleConfig} Bean reference
*/
String moduleConfigBeanName = service.module();
if (StringUtils.hasText(moduleConfigBeanName)) {
addPropertyReference(builder, "module", moduleConfigBeanName);
}
/**
* Add {@link com.alibaba.dubbo.config.RegistryConfig} Bean reference
*/
String[] registryConfigBeanNames = service.registry();
List<RuntimeBeanReference> registryRuntimeBeanReferences = toRuntimeBeanReferences(registryConfigBeanNames);
if (!registryRuntimeBeanReferences.isEmpty()) {
builder.addPropertyValue("registries", registryRuntimeBeanReferences);
}
/**
* Add {@link com.alibaba.dubbo.config.ProtocolConfig} Bean reference
*/
String[] protocolConfigBeanNames = service.protocol();
List<RuntimeBeanReference> protocolRuntimeBeanReferences = toRuntimeBeanReferences(protocolConfigBeanNames);
if (!registryRuntimeBeanReferences.isEmpty()) {
builder.addPropertyValue("protocols", protocolRuntimeBeanReferences);
}
return builder.getBeanDefinition();
}
private ManagedList<RuntimeBeanReference> toRuntimeBeanReferences(String... beanNames) {
ManagedList<RuntimeBeanReference> runtimeBeanReferences = new ManagedList<RuntimeBeanReference>();
if (!ObjectUtils.isEmpty(beanNames)) {
for (String beanName : beanNames) {
String resolvedBeanName = environment.resolvePlaceholders(beanName);
runtimeBeanReferences.add(new RuntimeBeanReference(resolvedBeanName));
}
}
return runtimeBeanReferences;
}
private void addPropertyReference(BeanDefinitionBuilder builder, String propertyName, String beanName) {
String resolvedBeanName = environment.resolvePlaceholders(beanName);
builder.addPropertyReference(propertyName, resolvedBeanName);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
}
package com.alibaba.dubbo.config.spring.context.annotation;
import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.dubbo.config.spring.ServiceBean;
import com.alibaba.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor;
import com.alibaba.dubbo.config.spring.beans.factory.annotation.ServiceAnnotationBeanPostProcessor;
import com.alibaba.dubbo.config.spring.util.BeanRegistrar;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.config.RuntimeBeanReference;
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.beans.factory.support.ManagedList;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import java.util.*;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.rootBeanDefinition;
import static org.springframework.beans.factory.support.BeanDefinitionReaderUtils.registerWithGeneratedName;
import static org.springframework.core.annotation.AnnotationUtils.findAnnotation;
import static org.springframework.util.ClassUtils.resolveClassName;
/**
* Dubbo {@link DubboComponentScan} Bean Registrar
......@@ -42,230 +29,40 @@ import static org.springframework.util.ClassUtils.resolveClassName;
* @see Service
* @see DubboComponentScan
* @see ImportBeanDefinitionRegistrar
* @see ServiceAnnotationBeanPostProcessor
* @see ReferenceAnnotationBeanPostProcessor
* @since 2.5.7
*/
public class DubboComponentScanRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware,
EnvironmentAware, BeanClassLoaderAware {
private final Log logger = LogFactory.getLog(getClass());
private ResourceLoader resourceLoader;
private Environment environment;
private ClassLoader classLoader;
public class DubboComponentScanRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
Set<String> packagesToScan = getPackagesToScan(importingClassMetadata);
registerServiceBeans(packagesToScan, registry);
registerServiceAnnotationBeanPostProcessor(packagesToScan, registry);
registerReferenceAnnotationBeanPostProcessor(registry);
}
/**
* Registers Beans whose classes was annotated {@link Service}
* Registers {@link ServiceAnnotationBeanPostProcessor}
*
* @param packagesToScan The base packages to scan
* @param packagesToScan packages to scan without resolving placeholders
* @param registry {@link BeanDefinitionRegistry}
* @since 2.5.8
*/
private void registerServiceBeans(Set<String> packagesToScan, BeanDefinitionRegistry registry) {
DubboClassPathBeanDefinitionScanner dubboClassPathBeanDefinitionScanner =
new DubboClassPathBeanDefinitionScanner(registry, environment, resourceLoader);
dubboClassPathBeanDefinitionScanner.addIncludeFilter(new AnnotationTypeFilter(Service.class));
for (String packageToScan : packagesToScan) {
Set<BeanDefinitionHolder> beanDefinitionHolders = dubboClassPathBeanDefinitionScanner.doScan(packageToScan);
for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) {
registerServiceBean(beanDefinitionHolder, registry);
}
if (logger.isInfoEnabled()) {
logger.info(beanDefinitionHolders.size() + " annotated @Service Components { " +
beanDefinitionHolders +
" } were scanned under package[" + packageToScan + "]");
}
}
}
private Class<?> resolveClass(BeanDefinitionHolder beanDefinitionHolder) {
BeanDefinition beanDefinition = beanDefinitionHolder.getBeanDefinition();
return resolveClass(beanDefinition);
}
private Class<?> resolveClass(BeanDefinition beanDefinition) {
String beanClassName = beanDefinition.getBeanClassName();
return resolveClassName(beanClassName, classLoader);
}
/**
* Registers {@link ServiceBean} from new annotated {@link Service} {@link BeanDefinition}
*
* @param beanDefinitionHolder
* @param registry
* @see ServiceBean
* @see BeanDefinition
*/
private void registerServiceBean(BeanDefinitionHolder beanDefinitionHolder, BeanDefinitionRegistry registry) {
Class<?> beanClass = resolveClass(beanDefinitionHolder);
Service service = findAnnotation(beanClass, Service.class);
Class<?> interfaceClass = resolveServiceInterfaceClass(beanClass, service);
String beanName = beanDefinitionHolder.getBeanName();
AbstractBeanDefinition serviceBeanDefinition = buildServiceBeanDefinition(service, interfaceClass, beanName);
registerWithGeneratedName(serviceBeanDefinition, registry);
}
private ManagedList<RuntimeBeanReference> toRuntimeBeanReferences(String... beanNames) {
ManagedList<RuntimeBeanReference> runtimeBeanReferences = new ManagedList<RuntimeBeanReference>();
if (!ObjectUtils.isEmpty(beanNames)) {
for (String beanName : beanNames) {
String resolvedBeanName = environment.resolvePlaceholders(beanName);
runtimeBeanReferences.add(new RuntimeBeanReference(resolvedBeanName));
}
}
return runtimeBeanReferences;
}
private void addPropertyReference(BeanDefinitionBuilder builder, String propertyName, String beanName) {
String resolvedBeanName = environment.resolvePlaceholders(beanName);
builder.addPropertyReference(propertyName, resolvedBeanName);
}
private AbstractBeanDefinition buildServiceBeanDefinition(Service service, Class<?> interfaceClass,
String annotatedServiceBeanName) {
BeanDefinitionBuilder builder = rootBeanDefinition(ServiceBean.class)
.addConstructorArgValue(service)
// References "ref" property to annotated-@Service Bean
.addPropertyReference("ref", annotatedServiceBeanName)
.addPropertyValue("interfaceClass", interfaceClass);
/**
* Add {@link com.alibaba.dubbo.config.ProviderConfig} Bean reference
*/
String providerConfigBeanName = service.provider();
if (StringUtils.hasText(providerConfigBeanName)) {
addPropertyReference(builder, "provider", providerConfigBeanName);
}
/**
* Add {@link com.alibaba.dubbo.config.MonitorConfig} Bean reference
*/
String monitorConfigBeanName = service.monitor();
if (StringUtils.hasText(monitorConfigBeanName)) {
addPropertyReference(builder, "monitor", monitorConfigBeanName);
}
/**
* Add {@link com.alibaba.dubbo.config.ApplicationConfig} Bean reference
*/
String applicationConfigBeanName = service.application();
if (StringUtils.hasText(applicationConfigBeanName)) {
addPropertyReference(builder, "application", applicationConfigBeanName);
}
/**
* Add {@link com.alibaba.dubbo.config.ModuleConfig} Bean reference
*/
String moduleConfigBeanName = service.module();
if (StringUtils.hasText(moduleConfigBeanName)) {
addPropertyReference(builder, "module", moduleConfigBeanName);
}
private void registerServiceAnnotationBeanPostProcessor(Set<String> packagesToScan, BeanDefinitionRegistry registry) {
/**
* Add {@link com.alibaba.dubbo.config.RegistryConfig} Bean reference
*/
String[] registryConfigBeanNames = service.registry();
List<RuntimeBeanReference> registryRuntimeBeanReferences = toRuntimeBeanReferences(registryConfigBeanNames);
if (!registryRuntimeBeanReferences.isEmpty()) {
builder.addPropertyValue("registries", registryRuntimeBeanReferences);
}
/**
* Add {@link com.alibaba.dubbo.config.ProtocolConfig} Bean reference
*/
String[] protocolConfigBeanNames = service.protocol();
List<RuntimeBeanReference> protocolRuntimeBeanReferences = toRuntimeBeanReferences(protocolConfigBeanNames);
if (!registryRuntimeBeanReferences.isEmpty()) {
builder.addPropertyValue("protocols", protocolRuntimeBeanReferences);
}
return builder.getBeanDefinition();
BeanDefinitionBuilder builder = rootBeanDefinition(ServiceAnnotationBeanPostProcessor.class);
builder.addConstructorArgValue(packagesToScan);
builder.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, registry);
}
private Class<?> resolveServiceInterfaceClass(Class<?> annotatedServiceBeanClass, Service service) {
Class<?> interfaceClass = service.interfaceClass();
if (void.class.equals(interfaceClass)) {
interfaceClass = null;
String interfaceClassName = service.interfaceName();
if (StringUtils.hasText(interfaceClassName)) {
if (ClassUtils.isPresent(interfaceClassName, classLoader)) {
interfaceClass = resolveClassName(interfaceClassName, classLoader);
}
}
}
if (interfaceClass == null) {
Class<?>[] allInterfaces = annotatedServiceBeanClass.getInterfaces();
if (allInterfaces.length > 0) {
interfaceClass = allInterfaces[0];
}
}
Assert.notNull(interfaceClass,
"@Service interfaceClass() or interfaceName() or interface class must be present!");
Assert.isTrue(interfaceClass.isInterface(),
"The type that was annotated @Service is not an interface!");
return interfaceClass;
}
/**
* Registers {@link ReferenceAnnotationBeanPostProcessor} into {@link BeanFactory}
*
......@@ -297,19 +94,4 @@ public class DubboComponentScanRegistrar implements ImportBeanDefinitionRegistra
return packagesToScan;
}
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
this.classLoader = classLoader;
}
}
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;
......@@ -12,21 +17,27 @@ 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
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
* @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
......@@ -60,19 +71,63 @@ public class DubboConfigBindingRegistrar implements ImportBeanDefinitionRegistra
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) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(configClass);
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();
AbstractBeanDefinition beanDefinition = builder.getBeanDefinition();
beanDefinition.setPropertyValues(resolveBeanPropertyValues(beanName, multiple, properties));
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(beanName, beanDefinition);
registerWithGeneratedName(beanDefinition, registry);
if (log.isInfoEnabled()) {
log.info("The BeanPostProcessor bean definition [" + processorClass.getName()
+ "] for dubbo config bean [name : " + beanName + "] has been registered.");
}
}
......@@ -143,7 +198,7 @@ public class DubboConfigBindingRegistrar implements ImportBeanDefinitionRegistra
String beanName = properties.get("id");
if (!StringUtils.hasText(beanName)) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(configClass);
BeanDefinitionBuilder builder = rootBeanDefinition(configClass);
beanName = BeanDefinitionReaderUtils.generateBeanName(builder.getRawBeanDefinition(), registry);
}
......
package com.alibaba.dubbo.config.spring.context.annotation;
import com.alibaba.dubbo.config.*;
import org.springframework.context.annotation.Configuration;
/**
* Dubbo {@link AbstractConfig Config} {@link Configuration}
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
* @see Configuration
* @see EnableDubboConfigBindings
* @see EnableDubboConfigBinding
* @see ApplicationConfig
* @see ModuleConfig
* @see RegistryConfig
* @see ProtocolConfig
* @see MonitorConfig
* @see ProviderConfig
* @see ConsumerConfig
* @since 2.5.8
*/
public class DubboConfigConfiguration {
/**
* Single Dubbo {@link AbstractConfig Config} Bean Binding
*/
@EnableDubboConfigBindings({
@EnableDubboConfigBinding(prefix = "dubbo.application", type = ApplicationConfig.class),
@EnableDubboConfigBinding(prefix = "dubbo.module", type = ModuleConfig.class),
@EnableDubboConfigBinding(prefix = "dubbo.registry", type = RegistryConfig.class),
@EnableDubboConfigBinding(prefix = "dubbo.protocol", type = ProtocolConfig.class),
@EnableDubboConfigBinding(prefix = "dubbo.monitor", type = MonitorConfig.class),
@EnableDubboConfigBinding(prefix = "dubbo.provider", type = ProviderConfig.class),
@EnableDubboConfigBinding(prefix = "dubbo.consumer", type = ConsumerConfig.class)
})
static class Single {
}
/**
* Multiple Dubbo {@link AbstractConfig Config} Bean Binding
*/
@EnableDubboConfigBindings({
@EnableDubboConfigBinding(prefix = "dubbo.application", type = ApplicationConfig.class, multiple = true),
@EnableDubboConfigBinding(prefix = "dubbo.module", type = ModuleConfig.class, multiple = true),
@EnableDubboConfigBinding(prefix = "dubbo.registry", type = RegistryConfig.class, multiple = true),
@EnableDubboConfigBinding(prefix = "dubbo.protocol", type = ProtocolConfig.class, multiple = true),
@EnableDubboConfigBinding(prefix = "dubbo.monitor", type = MonitorConfig.class, multiple = true),
@EnableDubboConfigBinding(prefix = "dubbo.provider", type = ProviderConfig.class, multiple = true),
@EnableDubboConfigBinding(prefix = "dubbo.consumer", type = ConsumerConfig.class, multiple = true)
})
static class Multiple {
}
}
package com.alibaba.dubbo.config.spring.context.annotation;
import com.alibaba.dubbo.config.AbstractConfig;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.type.AnnotationMetadata;
/**
* Dubbo {@link AbstractConfig Config} Registrar
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
* @see EnableDubboConfig
* @see DubboConfigConfiguration
* @since 2.5.8
*/
public class DubboConfigConfigurationSelector implements ImportSelector, Ordered {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
AnnotationAttributes attributes = AnnotationAttributes.fromMap(
importingClassMetadata.getAnnotationAttributes(EnableDubboConfig.class.getName()));
boolean multiple = attributes.getBoolean("multiple");
if (multiple) {
return of(DubboConfigConfiguration.Multiple.class.getName());
} else {
return of(DubboConfigConfiguration.Single.class.getName());
}
}
private static <T> T[] of(T... values) {
return values;
}
@Override
public int getOrder() {
return HIGHEST_PRECEDENCE;
}
}
package com.alibaba.dubbo.config.spring.context.annotation;
import com.alibaba.dubbo.config.ApplicationConfig;
import java.lang.annotation.*;
/**
* Equals {@link EnableDubboConfigBinding} for {@link ApplicationConfig} with "dubbo.application"
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
* @since 2.5.8
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@EnableDubboConfigBinding(prefix = "dubbo.application", type = ApplicationConfig.class)
public @interface EnableApplicationConfig {
}
package com.alibaba.dubbo.config.spring.context.annotation;
import com.alibaba.dubbo.config.AbstractConfig;
import org.springframework.core.annotation.AliasFor;
import java.lang.annotation.*;
/**
* Enables Dubbo components as Spring Beans, equals
* {@link DubboComponentScan} and {@link EnableDubboConfig} combination.
* <p>
* Note : {@link EnableDubbo} must base on Spring Framework 4.2 and above
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
* @see DubboComponentScan
* @see EnableDubboConfig
* @since 2.5.8
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@EnableDubboConfig
@DubboComponentScan
public @interface EnableDubbo {
/**
* Base packages to scan for annotated @Service classes.
* <p>
* Use {@link #scanBasePackageClasses()} for a type-safe alternative to String-based
* package names.
*
* @return the base packages to scan
* @see DubboComponentScan#basePackages()
*/
@AliasFor(annotation = DubboComponentScan.class, attribute = "basePackages")
String[] scanBasePackages() default {};
/**
* Type-safe alternative to {@link #scanBasePackages()} for specifying the packages to
* scan for annotated @Service classes. The package of each class specified will be
* scanned.
*
* @return classes from the base packages to scan
* @see DubboComponentScan#basePackageClasses
*/
@AliasFor(annotation = DubboComponentScan.class, attribute = "basePackageClasses")
Class<?>[] scanBasePackageClasses() default {};
/**
* It indicates whether {@link AbstractConfig} binding to multiple Spring Beans.
*
* @return the default value is <code>false</code>
* @see EnableDubboConfig#multiple()
*/
@AliasFor(annotation = EnableDubboConfig.class, attribute = "multiple")
boolean multipleConfig() default false;
}
package com.alibaba.dubbo.config.spring.context.annotation;
import com.alibaba.dubbo.config.*;
import org.springframework.context.annotation.Import;
import java.lang.annotation.*;
/**
* Equals {@link EnableDubboConfigBinding} for :
* <ul>
* <li>{@link ApplicationConfig} binding to property : "dubbo.application"</li>
* <li>{@link ModuleConfig} binding to property : "dubbo.module"</li>
* <li>{@link RegistryConfig} binding to property : "dubbo.registry"</li>
* <li>{@link ProtocolConfig} binding to property : "dubbo.protocol"</li>
* <li>{@link MonitorConfig} binding to property : "dubbo.monitor"</li>
* <li>{@link ProviderConfig} binding to property : "dubbo.provider"</li>
* <li>{@link ConsumerConfig} binding to property : "dubbo.consumer"</li>
* </ul>
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
* @see EnableDubboConfigBinding
* @see DubboConfigConfiguration
* @see DubboConfigConfigurationSelector
* @since 2.5.8
*/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@Import(DubboConfigConfigurationSelector.class)
public @interface EnableDubboConfig {
/**
* It indicates whether binding to multiple Spring Beans.
*
* @return the default value is <code>false</code>
*/
boolean multiple() default false;
}
......@@ -4,6 +4,7 @@ import com.alibaba.dubbo.config.AbstractConfig;
import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ModuleConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.spring.beans.factory.annotation.DubboConfigBindingBeanPostProcessor;
import org.springframework.context.annotation.Import;
import org.springframework.core.env.PropertySources;
......@@ -20,6 +21,7 @@ import java.lang.annotation.*;
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
* @see DubboConfigBindingRegistrar
* @see DubboConfigBindingBeanPostProcessor
* @see EnableDubboConfigBindings
* @since 2.5.8
*/
......
......@@ -17,7 +17,6 @@ package com.alibaba.dubbo.config.spring.extension;
import com.alibaba.dubbo.common.extension.ExtensionFactory;
import com.alibaba.dubbo.common.utils.ConcurrentHashSet;
import org.springframework.context.ApplicationContext;
import java.util.Set;
......
......@@ -21,16 +21,10 @@ import com.alibaba.dubbo.common.logger.Logger;
import com.alibaba.dubbo.common.logger.LoggerFactory;
import com.alibaba.dubbo.common.utils.ReflectUtils;
import com.alibaba.dubbo.common.utils.StringUtils;
import com.alibaba.dubbo.config.ArgumentConfig;
import com.alibaba.dubbo.config.ConsumerConfig;
import com.alibaba.dubbo.config.MethodConfig;
import com.alibaba.dubbo.config.ProtocolConfig;
import com.alibaba.dubbo.config.ProviderConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.*;
import com.alibaba.dubbo.config.spring.ReferenceBean;
import com.alibaba.dubbo.config.spring.ServiceBean;
import com.alibaba.dubbo.rpc.Protocol;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
......
......@@ -16,17 +16,10 @@
package com.alibaba.dubbo.config.spring.schema;
import com.alibaba.dubbo.common.Version;
import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ConsumerConfig;
import com.alibaba.dubbo.config.ModuleConfig;
import com.alibaba.dubbo.config.MonitorConfig;
import com.alibaba.dubbo.config.ProtocolConfig;
import com.alibaba.dubbo.config.ProviderConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.*;
import com.alibaba.dubbo.config.spring.AnnotationBean;
import com.alibaba.dubbo.config.spring.ReferenceBean;
import com.alibaba.dubbo.config.spring.ServiceBean;
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
/**
......
......@@ -21,7 +21,6 @@ import com.alibaba.dubbo.common.logger.LoggerFactory;
import com.alibaba.dubbo.common.status.Status;
import com.alibaba.dubbo.common.status.StatusChecker;
import com.alibaba.dubbo.config.spring.ServiceBean;
import org.springframework.context.ApplicationContext;
import javax.sql.DataSource;
......
......@@ -21,7 +21,6 @@ import com.alibaba.dubbo.common.logger.LoggerFactory;
import com.alibaba.dubbo.common.status.Status;
import com.alibaba.dubbo.common.status.StatusChecker;
import com.alibaba.dubbo.config.spring.ServiceBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.Lifecycle;
......
......@@ -10,7 +10,8 @@ import java.util.Collections;
import java.util.List;
import java.util.Map;
import static org.springframework.beans.factory.BeanFactoryUtils.*;
import static org.springframework.beans.factory.BeanFactoryUtils.beanNamesForTypeIncludingAncestors;
import static org.springframework.beans.factory.BeanFactoryUtils.beansOfTypeIncludingAncestors;
/**
* {@link BeanFactory} Utilities class
......
......@@ -20,13 +20,7 @@ import com.alibaba.dubbo.common.URL;
import com.alibaba.dubbo.common.extension.ExtensionLoader;
import com.alibaba.dubbo.common.utils.NetUtils;
import com.alibaba.dubbo.common.utils.StringUtils;
import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ConsumerConfig;
import com.alibaba.dubbo.config.ProtocolConfig;
import com.alibaba.dubbo.config.ProviderConfig;
import com.alibaba.dubbo.config.ReferenceConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.ServiceConfig;
import com.alibaba.dubbo.config.*;
import com.alibaba.dubbo.config.spring.action.DemoActionByAnnotation;
import com.alibaba.dubbo.config.spring.action.DemoActionBySetter;
import com.alibaba.dubbo.config.spring.annotation.consumer.AnnotationAction;
......@@ -45,7 +39,6 @@ import com.alibaba.dubbo.rpc.RpcContext;
import com.alibaba.dubbo.rpc.RpcException;
import com.alibaba.dubbo.rpc.service.GenericException;
import com.alibaba.dubbo.rpc.service.GenericService;
import junit.framework.Assert;
import org.junit.Ignore;
import org.junit.Test;
......@@ -55,12 +48,7 @@ import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.Collection;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assert.*;
import static org.junit.matchers.JUnitMatchers.containsString;
......
......@@ -16,7 +16,6 @@
package com.alibaba.dubbo.config.spring.action;
import com.alibaba.dubbo.config.spring.api.DemoService;
import org.springframework.beans.factory.annotation.Autowired;
/**
......
......@@ -17,7 +17,6 @@ package com.alibaba.dubbo.config.spring.annotation.consumer;
import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.spring.api.DemoService;
import org.springframework.stereotype.Controller;
/**
......
......@@ -10,7 +10,6 @@ import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ImportResource;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Component;
/**
* {@link ReferenceAnnotationBeanPostProcessor} Test
......
package com.alibaba.dubbo.config.spring.beans.factory.annotation;
import com.alibaba.dubbo.config.spring.api.DemoService;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ImportResource;
import org.springframework.context.annotation.PropertySource;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit4.SpringRunner;
/**
* {@link ServiceAnnotationBeanPostProcessor} Test
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
* @since 2.5.8
*/
@RunWith(SpringRunner.class)
@ContextConfiguration(
classes = {ServiceAnnotationBeanPostProcessorTest.TestConfiguration.class})
@TestPropertySource(properties = {
"package1 = com.alibaba.dubbo.config.spring.context.annotation",
"packagesToScan = ${package1}"
})
public class ServiceAnnotationBeanPostProcessorTest {
@Autowired
private DemoService demoService;
@Test
public void test() {
String value = demoService.sayName("Mercy");
Assert.assertEquals("Hello,Mercy", value);
}
@ImportResource("META-INF/spring/dubbo-annotation-provider.xml")
@PropertySource("META-INF/default.properties")
public static class TestConfiguration {
@Bean
public ServiceAnnotationBeanPostProcessor serviceAnnotationBeanPostProcessor
(@Value("${packagesToScan}") String... packagesToScan) {
return new ServiceAnnotationBeanPostProcessor(packagesToScan);
}
}
}
......@@ -2,17 +2,21 @@ package com.alibaba.dubbo.config.spring.context.annotation;
import com.alibaba.dubbo.config.spring.api.DemoService;
import com.alibaba.dubbo.config.spring.context.annotation.consumer.ConsumerConfiguration;
import com.alibaba.dubbo.config.spring.context.annotation.provider.DemoServiceImpl;
import com.alibaba.dubbo.config.spring.context.annotation.provider.ProviderConfiguration;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.aop.support.AopUtils;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.transaction.annotation.Transactional;
import static org.springframework.core.annotation.AnnotationUtils.findAnnotation;
/**
* {@link DubboComponentScanRegistrar} Test
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
* @since 2.5.7
* @since 2.5.8
*/
public class DubboComponentScanRegistrarTest {
......@@ -31,6 +35,14 @@ public class DubboComponentScanRegistrarTest {
Assert.assertEquals("Hello,Mercy", value);
Class<?> beanClass = AopUtils.getTargetClass(demoService);
// DemoServiceImpl with @Transactional
Assert.assertEquals(DemoServiceImpl.class, beanClass);
// Test @Transactional is present or not
Assert.assertNotNull(findAnnotation(beanClass, Transactional.class));
AnnotationConfigApplicationContext consumerContext = new AnnotationConfigApplicationContext();
consumerContext.register(ConsumerConfiguration.class);
......
package com.alibaba.dubbo.config.spring.context.annotation;
import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ModuleConfig;
import com.alibaba.dubbo.config.ProtocolConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.io.support.ResourcePropertySource;
import java.io.IOException;
/**
* {@link DubboConfigConfiguration} Test
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
* @since 2.5.8
*/
public class DubboConfigConfigurationTest {
private AnnotationConfigApplicationContext context;
@Before
public void before() throws IOException {
context = new AnnotationConfigApplicationContext();
ResourcePropertySource propertySource = new ResourcePropertySource("META-INF/config.properties");
context.getEnvironment().getPropertySources().addFirst(propertySource);
}
@After
public void after() {
context.close();
}
@Test
public void testSingle() throws IOException {
context.register(DubboConfigConfiguration.Single.class);
context.refresh();
// application
ApplicationConfig applicationConfig = context.getBean("applicationBean", ApplicationConfig.class);
Assert.assertEquals("dubbo-demo-application", applicationConfig.getName());
// module
ModuleConfig moduleConfig = context.getBean("moduleBean", ModuleConfig.class);
Assert.assertEquals("dubbo-demo-module", moduleConfig.getName());
// registry
RegistryConfig registryConfig = context.getBean(RegistryConfig.class);
Assert.assertEquals("zookeeper://192.168.99.100:32770", registryConfig.getAddress());
// protocol
ProtocolConfig protocolConfig = context.getBean(ProtocolConfig.class);
Assert.assertEquals("dubbo", protocolConfig.getName());
Assert.assertEquals(Integer.valueOf(20880), protocolConfig.getPort());
}
@Test
public void testMultiple() {
context.register(DubboConfigConfiguration.Multiple.class);
context.refresh();
// application
ApplicationConfig applicationConfig = context.getBean("applicationBean", ApplicationConfig.class);
Assert.assertEquals("dubbo-demo-application", applicationConfig.getName());
ApplicationConfig applicationBean2 = context.getBean("applicationBean2", ApplicationConfig.class);
Assert.assertEquals("dubbo-demo-application2", applicationBean2.getName());
ApplicationConfig applicationBean3 = context.getBean("applicationBean3", ApplicationConfig.class);
Assert.assertEquals("dubbo-demo-application3", applicationBean3.getName());
}
}
package com.alibaba.dubbo.config.spring.context.annotation;
import com.alibaba.dubbo.config.ApplicationConfig;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.PropertySource;
/**
* {@link EnableApplicationConfig} Test
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
* @since 2.5.8
*/
public class EnableApplicationConfigTest {
@Test
public void test() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(TestConfig.class);
context.refresh();
ApplicationConfig applicationConfig = context.getBean("applicationBean", ApplicationConfig.class);
Assert.assertEquals("dubbo-demo-application", applicationConfig.getName());
}
@EnableApplicationConfig
@PropertySource("META-INF/config.properties")
private static class TestConfig {
}
}
package com.alibaba.dubbo.config.spring.context.annotation;
import com.alibaba.dubbo.config.*;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.PropertySource;
/**
* {@link EnableDubboConfig} Test
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
* @since 2.5.8
*/
public class EnableDubboConfigTest {
@Test
public void testSingle() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(TestConfig.class);
context.refresh();
// application
ApplicationConfig applicationConfig = context.getBean("applicationBean", ApplicationConfig.class);
Assert.assertEquals("dubbo-demo-application", applicationConfig.getName());
// module
ModuleConfig moduleConfig = context.getBean("moduleBean", ModuleConfig.class);
Assert.assertEquals("dubbo-demo-module", moduleConfig.getName());
// registry
RegistryConfig registryConfig = context.getBean(RegistryConfig.class);
Assert.assertEquals("zookeeper://192.168.99.100:32770", registryConfig.getAddress());
// protocol
ProtocolConfig protocolConfig = context.getBean(ProtocolConfig.class);
Assert.assertEquals("dubbo", protocolConfig.getName());
Assert.assertEquals(Integer.valueOf(20880), protocolConfig.getPort());
// monitor
MonitorConfig monitorConfig = context.getBean(MonitorConfig.class);
Assert.assertEquals("zookeeper://127.0.0.1:32770", monitorConfig.getAddress());
// provider
ProviderConfig providerConfig = context.getBean(ProviderConfig.class);
Assert.assertEquals("127.0.0.1", providerConfig.getHost());
// consumer
ConsumerConfig consumerConfig = context.getBean(ConsumerConfig.class);
Assert.assertEquals("netty", consumerConfig.getClient());
}
@Test
public void testMultiple() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.register(TestMultipleConfig.class);
context.refresh();
// application
ApplicationConfig applicationConfig = context.getBean("applicationBean", ApplicationConfig.class);
Assert.assertEquals("dubbo-demo-application", applicationConfig.getName());
ApplicationConfig applicationBean2 = context.getBean("applicationBean2", ApplicationConfig.class);
Assert.assertEquals("dubbo-demo-application2", applicationBean2.getName());
ApplicationConfig applicationBean3 = context.getBean("applicationBean3", ApplicationConfig.class);
Assert.assertEquals("dubbo-demo-application3", applicationBean3.getName());
}
@EnableDubboConfig(multiple = true)
@PropertySource("META-INF/config.properties")
private static class TestMultipleConfig {
}
@EnableDubboConfig
@PropertySource("META-INF/config.properties")
private static class TestConfig {
}
}
package com.alibaba.dubbo.config.spring.context.annotation;
import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.spring.api.DemoService;
import com.alibaba.dubbo.config.spring.context.annotation.consumer.test.TestConsumerConfiguration;
import com.alibaba.dubbo.config.spring.context.annotation.provider.DemoServiceImpl;
import org.junit.Assert;
import org.junit.Test;
import org.springframework.aop.support.AopUtils;
import org.springframework.context.annotation.*;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionException;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.Transactional;
import static org.springframework.core.annotation.AnnotationUtils.findAnnotation;
/**
* {@link EnableDubbo} Test
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
* @since 2.5.8
*/
public class EnableDubboTest {
@Test
public void test() {
AnnotationConfigApplicationContext providerContext = new AnnotationConfigApplicationContext();
providerContext.register(TestProviderConfiguration.class);
providerContext.refresh();
DemoService demoService = providerContext.getBean(DemoService.class);
String value = demoService.sayName("Mercy");
Assert.assertEquals("Hello,Mercy", value);
Class<?> beanClass = AopUtils.getTargetClass(demoService);
// DemoServiceImpl with @Transactional
Assert.assertEquals(DemoServiceImpl.class, beanClass);
// Test @Transactional is present or not
Assert.assertNotNull(findAnnotation(beanClass, Transactional.class));
AnnotationConfigApplicationContext consumerContext = new AnnotationConfigApplicationContext();
consumerContext.register(TestConsumerConfiguration.class);
consumerContext.refresh();
TestConsumerConfiguration consumerConfiguration = consumerContext.getBean(TestConsumerConfiguration.class);
demoService = consumerConfiguration.getDemoService();
value = demoService.sayName("Mercy");
Assert.assertEquals("Hello,Mercy", value);
TestConsumerConfiguration.Child child = consumerContext.getBean(TestConsumerConfiguration.Child.class);
// From Child
demoService = child.getDemoServiceFromChild();
Assert.assertNotNull(demoService);
value = demoService.sayName("Mercy");
Assert.assertEquals("Hello,Mercy", value);
// From Parent
demoService = child.getDemoServiceFromParent();
Assert.assertNotNull(demoService);
value = demoService.sayName("Mercy");
Assert.assertEquals("Hello,Mercy", value);
// From Ancestor
demoService = child.getDemoServiceFromAncestor();
Assert.assertNotNull(demoService);
value = demoService.sayName("Mercy");
Assert.assertEquals("Hello,Mercy", value);
// Test dubbo-annotation-consumer2 bean presentation
ApplicationConfig applicationConfig = consumerContext.getBean("dubbo-annotation-consumer2", ApplicationConfig.class);
// Test multiple binding
Assert.assertEquals("dubbo-consumer2", applicationConfig.getName());
// Test dubbo-annotation-consumer2 bean presentation
RegistryConfig registryConfig = consumerContext.getBean("my-registry2", RegistryConfig.class);
// Test multiple binding
Assert.assertEquals("N/A", registryConfig.getAddress());
providerContext.close();
consumerContext.close();
}
@EnableDubbo(scanBasePackages = "com.alibaba.dubbo.config.spring.context.annotation.provider")
@ComponentScan(basePackages = "com.alibaba.dubbo.config.spring.context.annotation.provider")
@PropertySource("META-INF/dubbb-provider.properties")
@EnableTransactionManagement
public static class TestProviderConfiguration {
@Primary
@Bean
public PlatformTransactionManager platformTransactionManager() {
return new PlatformTransactionManager() {
@Override
public TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
return null;
}
@Override
public void commit(TransactionStatus status) throws TransactionException {
}
@Override
public void rollback(TransactionStatus status) throws TransactionException {
}
};
}
}
}
package com.alibaba.dubbo.config.spring.context.annotation.consumer;
import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.spring.api.DemoService;
import com.alibaba.dubbo.config.spring.context.annotation.DubboComponentScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
......@@ -11,16 +12,46 @@ import org.springframework.context.annotation.PropertySource;
/**
* @author ken.lj
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
* @date 2017/11/3
*/
@Configuration("consumerConfiguration")
@DubboComponentScan(
basePackageClasses = ConsumerConfiguration.class
)
@ImportResource("META-INF/spring/dubbo-annotation-consumer.xml")
@PropertySource("META-INF/default.properties")
public class ConsumerConfiguration {
/**
* 当前应用配置,替代 XML 方式配置:
* <prev>
* &lt;dubbo:application name="dubbo-annotation-consumer"/&gt;
* </prev>
*
* @return {@link ApplicationConfig} Bean
*/
@Bean("dubbo-annotation-consumer")
public ApplicationConfig applicationConfig() {
ApplicationConfig applicationConfig = new ApplicationConfig();
applicationConfig.setName("dubbo-annotation-consumer");
return applicationConfig;
}
/**
* 当前连接注册中心配置,替代 XML 方式配置:
* <prev>
* &lt;dubbo:registry address="N/A"/&gt;
* </prev>
*
* @return {@link RegistryConfig} Bean
*/
@Bean
public RegistryConfig registryConfig() {
RegistryConfig registryConfig = new RegistryConfig();
registryConfig.setAddress("N/A");
return registryConfig;
}
@Reference(version = "2.5.7", url = "dubbo://127.0.0.1:12345")
private DemoService demoService;
......
package com.alibaba.dubbo.config.spring.context.annotation.consumer.test;
import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.spring.api.DemoService;
import com.alibaba.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.PropertySource;
import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
* Test Consumer Configuration
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
* @since 2.5.7
*/
@EnableDubbo(scanBasePackageClasses = TestConsumerConfiguration.class, multipleConfig = true)
@PropertySource("META-INF/dubbb-consumer.properties")
@EnableTransactionManagement
public class TestConsumerConfiguration {
@Reference(version = "2.5.7", url = "dubbo://127.0.0.1:12345", application = "dubbo-annotation-consumer")
private DemoService demoService;
public DemoService getDemoService() {
return demoService;
}
public void setDemoService(DemoService demoService) {
this.demoService = demoService;
}
@Bean
public TestConsumerConfiguration.Child c() {
return new TestConsumerConfiguration.Child();
}
public static abstract class Ancestor {
@Reference(version = "2.5.7", url = "dubbo://127.0.0.1:12345", application = "dubbo-annotation-consumer")
private DemoService demoServiceFromAncestor;
public DemoService getDemoServiceFromAncestor() {
return demoServiceFromAncestor;
}
public void setDemoServiceFromAncestor(DemoService demoServiceFromAncestor) {
this.demoServiceFromAncestor = demoServiceFromAncestor;
}
}
public static abstract class Parent extends TestConsumerConfiguration.Ancestor {
private DemoService demoServiceFromParent;
public DemoService getDemoServiceFromParent() {
return demoServiceFromParent;
}
@Reference(version = "2.5.7", url = "dubbo://127.0.0.1:12345", application = "dubbo-annotation-consumer")
public void setDemoServiceFromParent(DemoService demoServiceFromParent) {
this.demoServiceFromParent = demoServiceFromParent;
}
}
public static class Child extends TestConsumerConfiguration.Parent {
@Reference(version = "2.5.7", url = "dubbo://127.0.0.1:12345", application = "dubbo-annotation-consumer")
private DemoService demoServiceFromChild;
public DemoService getDemoServiceFromChild() {
return demoServiceFromChild;
}
public void setDemoServiceFromChild(DemoService demoServiceFromChild) {
this.demoServiceFromChild = demoServiceFromChild;
}
}
}
package com.alibaba.dubbo.config.spring.context.annotation;
package com.alibaba.dubbo.config.spring.context.annotation.provider;
import com.alibaba.dubbo.config.spring.api.Box;
import com.alibaba.dubbo.config.spring.api.DemoService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
;
/**
* {@link DemoService} Service implementation
*
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
* @since 2.5.7
* @since 2.5.8
*/
@com.alibaba.dubbo.config.annotation.Service(
version = "2.5.7",
......@@ -19,6 +19,7 @@ import org.springframework.stereotype.Service;
registry = "${demo.service.registry}"
)
@Service
@Transactional
public class DemoServiceImpl implements DemoService {
@Override
......
package com.alibaba.dubbo.config.spring.context.annotation.provider;
import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ProtocolConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.spring.context.annotation.DubboComponentScan;
import com.alibaba.dubbo.rpc.Protocol;
import com.sun.org.apache.regexp.internal.RE;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ImportResource;
import org.springframework.context.annotation.Primary;
import org.springframework.context.annotation.PropertySource;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionException;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.EnableTransactionManagement;
/**
* @author ken.lj
* @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
* @date 2017/11/3
*/
@DubboComponentScan(basePackages = "com.alibaba.dubbo.config.spring.context.annotation")
@ImportResource("META-INF/spring/dubbo-annotation-provider.xml")
@DubboComponentScan(basePackages = "com.alibaba.dubbo.config.spring.context.annotation.provider")
@PropertySource("META-INF/default.properties")
@EnableTransactionManagement
public class ProviderConfiguration {
/**
* 当前应用配置,替代 XML 方式配置:
* <prev>
* &lt;dubbo:application name="dubbo-annotation-provider"/&gt;
* </prev>
*
* @return {@link ApplicationConfig} Bean
*/
@Bean("dubbo-annotation-provider")
public ApplicationConfig applicationConfig() {
ApplicationConfig applicationConfig = new ApplicationConfig();
applicationConfig.setName("dubbo-annotation-provider");
return applicationConfig;
}
/**
* 当前连接注册中心配置,替代 XML 方式配置:
* <prev>
* &lt;dubbo:registry id="my-registry" address="N/A"/&gt;
* </prev>
*
* @return {@link RegistryConfig} Bean
*/
@Bean("my-registry")
public RegistryConfig registryConfig() {
RegistryConfig registryConfig = new RegistryConfig();
registryConfig.setAddress("N/A");
return registryConfig;
}
/**
* 当前连接注册中心配置,替代 XML 方式配置:
* <prev>
* &lt;dubbo:protocol name="dubbo" port="12345"/&gt;
* </prev>
*
* @return {@link ProtocolConfig} Bean
*/
@Bean("dubbo")
public ProtocolConfig protocolConfig() {
ProtocolConfig protocolConfig = new ProtocolConfig();
protocolConfig.setName("dubbo");
protocolConfig.setPort(12345);
return protocolConfig;
}
@Primary
@Bean
public PlatformTransactionManager platformTransactionManager() {
return new PlatformTransactionManager() {
@Override
public TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException {
return null;
}
@Override
public void commit(TransactionStatus status) throws TransactionException {
}
@Override
public void rollback(TransactionStatus status) throws TransactionException {
}
};
}
}
......@@ -15,12 +15,7 @@
*/
package com.alibaba.dubbo.config.spring.filter;
import com.alibaba.dubbo.rpc.Filter;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Protocol;
import com.alibaba.dubbo.rpc.Result;
import com.alibaba.dubbo.rpc.RpcException;
import com.alibaba.dubbo.rpc.*;
import com.alibaba.dubbo.rpc.cluster.LoadBalance;
/**
......
application.prefix = dubbo.application.
# single bean definition
## application
dubbo.application.id = applicationBean
dubbo.application.name = dubbo-demo-application
## module
dubbo.module.id = moduleBean
dubbo.module.name = dubbo-demo-module
## registry
dubbo.registry.address = zookeeper://192.168.99.100:32770
## protocol
dubbo.protocol.name = dubbo
dubbo.protocol.port = 20880
## monitor
dubbo.monitor.address = zookeeper://127.0.0.1:32770
## provider
dubbo.provider.host = 127.0.0.1
## consumer
dubbo.consumer.client = netty
# multiple Bean definition
dubbo.application.applicationBean.name = dubbo-demo-application
dubbo.application.applicationBean2.name = dubbo-demo-application2
......
# Dubbo Consumer Properties as an alternative for
# Spring XML Bean definition : META-INF/spring/dubbo-annotation-consumer.xml
demo.service.application = dubbo-annotation-consumer
demo.service.registry = my-registry
## Dubbo configs binding properties
### <dubbo:application name="dubbo-annotation-consumer"/>
dubbo.application.dubbo-annotation-consumer.name = Dubbo Consumer
dubbo.application.dubbo-annotation-consumer2.name = dubbo-consumer2
### <dubbo:registry id="my-registry" address="N/A"/>
dubbo.registry.my-registry.address = N/A
dubbo.registry.my-registry2.address = N/A
\ No newline at end of file
# Dubbo Provider Properties as an alternative for
# Spring XML Bean definition : META-INF/spring/dubbo-annotation-provider.xml
## Service Providers' Placeholders for com.alibaba.dubbo.config.spring.context.annotation.provider.DemoServiceImpl
demo.service.application = dubbo-annotation-provider
demo.service.protocol = dubbo
demo.service.registry = my-registry
## Dubbo configs binding properties
### <dubbo:application name="dubbo-annotation-provider"/>
dubbo.application.id = dubbo-annotation-provider
dubbo.application.name = Dubbo Provider
### <dubbo:registry id="my-registry" address="N/A"/>
dubbo.registry.id = my-registry
dubbo.registry.address = N/A
### <dubbo:protocol name="dubbo" port="12345"/>
dubbo.protocol.id = dubbo
dubbo.protocol.name = dubbo
dubbo.protocol.port = 12345
\ No newline at end of file
......@@ -21,6 +21,12 @@
<param name="ConversionPattern" value="[%d{dd/MM/yy hh:mm:ss:sss z}] %t %5p %c{2}: %m%n"/>
</layout>
</appender>
<logger name="com.alibaba.dubbo.config.spring" additivity="false">
<level value="DEBUG"/>
<appender-ref ref="CONSOLE"/>
</logger>
<root>
<level value="INFO"/>
<appender-ref ref="CONSOLE"/>
......
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册