package com.reger.dubbo.config; 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; import java.util.ArrayList; import java.util.List; import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.aop.support.AopUtils; import org.springframework.beans.BeansException; import org.springframework.beans.factory.BeanClassLoaderAware; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinitionHolder; import org.springframework.beans.factory.config.BeanFactoryPostProcessor; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; 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.BeanDefinitionRegistry; import org.springframework.beans.factory.support.ManagedList; import org.springframework.context.EnvironmentAware; import org.springframework.context.ResourceLoaderAware; import org.springframework.core.env.Environment; import org.springframework.core.io.ResourceLoader; 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 com.alibaba.dubbo.common.Constants; import com.alibaba.dubbo.config.AbstractConfig; import com.alibaba.dubbo.config.ProtocolConfig; import com.alibaba.dubbo.config.RegistryConfig; import com.alibaba.dubbo.config.annotation.Service; import com.alibaba.dubbo.config.spring.ServiceBean; import com.alibaba.dubbo.config.spring.beans.factory.annotation.InjectAnnotationBeanPostProcessor; import com.alibaba.dubbo.config.spring.beans.factory.annotation.ReferenceAnnotationBeanPostProcessor; import com.alibaba.dubbo.config.spring.context.annotation.DubboClassPathBeanDefinitionScanner; import com.alibaba.dubbo.config.spring.util.BeanRegistrar; public class AnnotationBean extends AbstractConfig implements DisposableBean, BeanFactoryPostProcessor, ResourceLoaderAware, EnvironmentAware, BeanClassLoaderAware { private static final long serialVersionUID = 1L; private final Logger logger = LoggerFactory.getLogger(AnnotationBean.class); protected BeanDefinitionRegistry registry; private ResourceLoader resourceLoader; private Environment environment; private ClassLoader classLoader; private String[] annotationPackages; @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; } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { this.registry = (BeanDefinitionRegistry) beanFactory; BeanRegistrar.registerInfrastructureBean(registry, InjectAnnotationBeanPostProcessor.BEAN_NAME, InjectAnnotationBeanPostProcessor.class); BeanRegistrar.registerInfrastructureBean(registry, ReferenceAnnotationBeanPostProcessor.BEAN_NAME, ReferenceAnnotationBeanPostProcessor.class); } public void setPackage(String annotationPackage) { if (StringUtils.hasText(annotationPackage)) { this.annotationPackages = trims(annotationPackage); } else { this.annotationPackages = new String[] {}; } } protected void postProcessAnnotationPackageService() { if (this.annotationPackages.length == 0) { return; } DubboClassPathBeanDefinitionScanner definitionScanner = new DubboClassPathBeanDefinitionScanner( registry, environment, resourceLoader); definitionScanner.addIncludeFilter(new AnnotationTypeFilter(Service.class)); Set<BeanDefinitionHolder> definitionHolders = definitionScanner.doScan(this.annotationPackages); for (BeanDefinitionHolder definitionHolder : definitionHolders) { registerServiceBean(definitionHolder, registry); } logger.debug("{} annotated @Service Components { {} } were scanned under package[{}]", definitionHolders.size(), definitionHolders, this.annotationPackages); } /** * 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(); if(interfaceClass==null){ Class<?>[] interfacess = beanClass.getInterfaces(); Assert.isTrue(interfacess.length!=0, beanClass+"没有实现任何接口,不可以发布服务"); for (Class<?> interfaces : interfacess) { AbstractBeanDefinition serviceBeanDefinition = buildServiceBeanDefinition(service, interfaces, beanName); registerWithGeneratedName(serviceBeanDefinition, registry); } }else{ 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) { runtimeBeanReferences.add(new RuntimeBeanReference(beanName)); } } return runtimeBeanReferences; } private AbstractBeanDefinition buildServiceBeanDefinition(Service service, Class<?> interfaceClass, String annotatedServiceBeanName) { BeanDefinitionBuilder builder = rootBeanDefinition(ServiceBean.class) .addConstructorArgValue(service) .addPropertyReference("ref", annotatedServiceBeanName) .addPropertyValue("interfaceClass", interfaceClass); /** * Add {@link com.alibaba.dubbo.config.ProviderConfig} Bean reference */ String providerConfigBeanName = service.provider(); if (StringUtils.hasText(providerConfigBeanName)) { builder.addPropertyReference("provider", providerConfigBeanName); } /** * Add {@link com.alibaba.dubbo.config.MonitorConfig} Bean reference */ String monitorConfigBeanName = service.monitor(); if (StringUtils.hasText(monitorConfigBeanName)) { builder.addPropertyReference("monitor", monitorConfigBeanName); } /** * Add {@link com.alibaba.dubbo.config.ApplicationConfig} Bean reference */ String applicationConfigBeanName = service.application(); if (StringUtils.hasText(applicationConfigBeanName)) { builder.addPropertyReference("application", applicationConfigBeanName); } /** * Add {@link com.alibaba.dubbo.config.ModuleConfig} Bean reference */ String moduleConfigBeanName = service.module(); if (StringUtils.hasText(moduleConfigBeanName)) { builder.addPropertyReference("application", 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 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){ return null; } 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); } /** * 切包名字符串 * * @param annotationPackage * 包名 * @return 切好后的字符串 */ private String[] trims(String annotationPackage) { String[] tmpes = Constants.COMMA_SPLIT_PATTERN.split(annotationPackage); List<String> packages = new ArrayList<String>(); for (String tmpe : tmpes) { tmpe = tmpe.trim(); if (!tmpe.isEmpty()) { packages.add(tmpe); } } return packages.toArray(new String[] {}); } /** * 匹配类实例是否在包中 * * @param bean * 被判断的类 * @return 是否包含 */ protected boolean isMatchPackage(Object bean) { if (annotationPackages.length == 0) { return true; } String beanClassName = this.getOriginalClass(bean).getName(); for (String pkg : annotationPackages) { if (beanClassName.startsWith(pkg)) { return true; } } return false; } /** * 获取bean的原始类型 * * @param bean * 输入的bean对象 * @return bean的原始类型 */ private Class<?> getOriginalClass(Object bean) { if (AopUtils.isAopProxy(bean)) { return AopUtils.getTargetClass(bean); } return bean.getClass(); } @Override public void destroy() throws Exception { logger.info("dubbo开始关闭...."); ProtocolConfig.destroyAll(); RegistryConfig.destroyAll(); } }